i have a class which inherits from EndpointsModel
class User( EndpointsModel ):
name = ndb.StructuredProperty( Name, required=True )
dateOfBirth = ndb.DateProperty(required=True)
userName = ndb.StringProperty( required=True )
emailId = ndb.StringProperty( required=True )
Now, suppose i want to update the name for some user with some username. Since, the methods for User expects a User object as input and output, do i have to create a separate message class for name and then use it to update name like i would do if i was not using endpoints-proto-datastore ?
You can define request_fields in your API method to limit the "request message" to a subset of the fields in User
#User.method(path='/user/{id}',
http_method='PUT',
name='update',
request_fields=('id', 'name'))
def update_user(self, user):
...
Related
I am trying to access the username attribute of a Django User object from a Profile object that is related by a OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
username = models.TextField(default=user.username, primary_key=True)
image = models.ImageField(upload_to='images/profile')
header = models.CharField(max_length=64)
slug = AutoSlugField(populate_from='x')
bio = models.CharField(max_length=300, blank=True)
The intent of this is to be able to get a Profile object using a ReactJS frontend by passing the username provided at login back to a profile detail endpoint in a Django API, where the username is the primary key for the endpoint.
path('<pk>/profile/', ShowProfilePageView.as_view(), name='show_profile_page'),
I've tried many different things for the default argument passed to the Profile username attribute, but nothing is working so far. Is this even possible?
Addendum 1: ShowProfilePageView view
class ShowProfilePageView(generics.RetrieveUpdateDestroyAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
model = Profile
I think you can simply override the lookup_field in the View, like this:
class ShowProfilePageView(generics.RetrieveUpdateDestroyAPIView):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
model = Profile
lookup_field='user__username'
lookup_url_kwarg='username'
And update the url like this:
path('<str:username>/profile/', ShowProfilePageView.as_view(), name='show_profile_page')
Because through lookup_field, the view will look for the value in User model from Profile model. And lookup_url_kwargs is to map what value it should use from urls. More information can be found in documentation. FYI you should remove username field from Profile model, it should use AutoField(which is the default field for primary key in models).
To access the attribute of one-to-one field you can just do this:
profile = Profile.objects.get(pk='profile_pk') # an object of profile
username = profile.user.username
To search Profile via username:
profile = Profile.objects.get(user=User.objects.get(username='username'))
Thus, you don't need to define username field on Profile class
Here is how my model looks like:
class Maintab(models.Model):
email = models.CharField(max_length=255)
username = models.CharField(max_length=255)
password = models.CharField(max_length=255)
lab_name = models.CharField(max_length=255)
type = models.CharField(max_length=255)
def __str__(self):
return self.username
I want to append the User table that looks after the login, with the username and password of my Maintab model. If only the username and password of the user table could get updated.
Or if I could use Maintab as my Custom UserModel (but it would not have attributes like is_active, is_staff, etc)
Seems like creating your own user models by subclassing the existing user model is the right solution as it enables you to use the existing django code while also adding your own user attributes.
Here is a link to the Django documentation where they describe how to do this:
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
All I am trying to produce is an entity that holds a unique username, and a unique device ID, and the ability to return an error if either of these conditions are not met on submission.
The only way I can see is to perform a query within a transaction, then filter the results. This however requires an ancestor (which seems unnecessary for a single simple entity).
What is the best method to go about doing this?
Here is an example that does what you want.
I put 2 entities to show you also how to make relationships
class Person(ndb.Expando):
registration_date = ndb.DateTimeProperty(auto_now_add=True)
#property
def info(self):
info = PersonInfo.query(ancestor=self.key).get()
return info
class PersonInfo(ndb.Expando):
email = ndb.StringProperty()
nick_name = ndb.StringProperty()
edit_date = ndb.DateTimeProperty(auto_now=True)
Later in the controller for register:
class RegisterPersonHandler(webapp2.RequestHandler):
def get(self):
user = users.get_current_user() #Stub here
if not user:
self.redirect(users.create_login_url(self.request.uri), abort=True)
return
person = Person.get_or_insert(user.user_id())
if not self._register(person, user):
# more logging is needed
logging.warning('Warning registration failed')
return
#ndb.transactional()
def _register(self, person, user):
''' Registration process happens here
'''
# check if the person has info and if not create it
info = PersonInfo.query(ancestor=person.key).get()
if not info:
info = PersonInfo(id=user.user_id(), parent=person.key)
info.nick_name = user.nickname()
info.email = user.email()
info.put()
return True
To answer also the comment question:
How can you programatically tell whether the returned entity is a new
or existing one though?
Try checking against a property that is default. Eg creation_date etc.
Though you can also check on something you need or on another entity's existence like I do because I expect the data to be consistent, and if not then create the bond.
I am working with google app engine,
I have 2 classes namely A and B and one db model say DB,
I have processed object of DB model in class A, and i want
to send the same object in class B, How can i do this?
Here is my code,
class Candidate(db.Model):
name = db.StringProperty()
lastname = db.StringProperty()
email = db.StringProperty()
mobno = db.StringProperty()
class A(webapp2.RequestHandler):
def post(self):
currCandidate = Candidate(key_name=self.request.get('email'))
currCandidate.name = self.request.get('name')
currCandidate.lastname=self.request.get('lname')
currCandidate.email=self.request.get('email')
currCandidate.mobno=self.request.get('mobno')
class B(webapp2.RequestHandler):
def get(self):
# currCandidate
# want to access currCandidate object here,
# currCandidate is from class A
I want to access the currCandidate object from class B.
Your 'A' handler is a POST, and gets a Candidate object via keyname, which is the email request parameter. Can you not use the same mechanism for the 'B' handler? This is a GET so you will need to pass the email in as a URL parameter. For example https://yourapp.appspot.com/b?email=someemail#domain.com.
You can then pick it up again with the same code you are using in the POST - currCandidate = Candidate(key_name=self.request.get('email')).
since you are creating a web app,you can store the object in session variable and access it in other class.In java this is done by serializing the object and storing it in session variable
I have Guest model in my app:
class Guest(models.Model):
event = models.ForeignKey(Event, related_name='guests')
contact = models.ForeignKey(Contact, related_name='guests')
attending_status = models.CharField(max_length=32, choices=ATTENDING_CHOICES, default='no_rsvp')
number_of_guests = models.SmallIntegerField(default=0)
comment = models.CharField(max_length=255, blank=True, default='')
updated = models.DateTimeField(blank=True, null=True)
Event and Contact I fill up by myself in Admin when creating a guest. On the site all I want is a guest to fill up the form where he refreshes his attending status, points out number of guests and leaves a comment.
class RSVPForm(forms.Form):
attending = forms.ChoiceField(choices=VISIBLE_ATTENDING_CHOICES, initial='yes', widget=forms.RadioSelect)
number_of_guests = forms.IntegerField(initial=0)
comment = forms.CharField(max_length=255, required=False, widget=forms.Textarea)
How can I save the changes to the Guest model instance? How can I access the guest's id when saving the changes to his profile?
You are probably looking for Django's ModelForms. Instead of subclassing forms.Form in your RSVPForm class, you should subclass forms.ModelForm. Then you can use the features of the model form class to help you achieve what you want (hide some fields, etc). An example is below:
class RSVPForm(forms.ModelForm):
class Meta:
model = Guest
fields = ('attending_status', 'number_of_guests', 'comment')
This will do essentially what you want, but you will need to remember to provide an instance keyword argument to the form constructor in your view function. This argument is the instance of the Guest model you will be updating with the form.
form = RSVPForm(instance=guest_object)
Now calls to the form.save() method will automatically save the new data to this Guest object instance. You just need to make sure that you always pass the instance keyword argument, even when using request.POST:
form = RSVPForm(request.POST, instance=guest_object)