How to store user_id in admin of wagtail (non page model)? - wagtail

I have some model like below in my blog-like website, I hope different user can query their own data. SO, I need save user id in my model.
However, modeladmin of wagtail only has get_queryset() but no save_model()
class Info(Orderable):
user = models.ForeignKey('auth.User',
on_delete=models.CASCADE,
blank=False, null=True,
related_name='+',)
Is there any way to store user id in wagtail admin panel?

The other way is pre-populate it, I try to do this and it's work well.
def create_view(self, request):
view = super().create_view(request)
self._set_username(view, request)
return view
def _set_username(self, view, request):
if hasattr(view, 'context_data'):
form = view.context_data['form']
form.fields['name'].widget.attrs['value'] = request.user

if you mean (from) admin, yes you can, but if you mean to admin panel from the model class, no you can't, handling the request is job of Views(the controllers) once the URL been requested, the view evaluate many things, one of them is request.user, and this one is an object of User model, you can then ask for id by (requested.user.id).. but of course in the views.py, or wagtail_hooks.py

Related

Django Models: Accessing Parent Object Attribute Within a Related Object Using OneToOneField

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

Appending data to User Model in Django

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

Django REST Framework: slug or serializer

I am using Django Rest Framework for a project and I have a nested serializer like this:
class TopSerializer(serializers.ModelSerializer):
contact = (something goes here)
email = (something goes here)
For POST, PATCH, PUT, DELETE I want to specify these values with a slug. Suppose each class (Contact, Email) has a member called resource_id and that is my slug. For these methods I could use:
class TopSerializer(serializers.ModelSerializer):
contact = serializers.SlugRelatedField(read_only=False, slug_field='resource_id')
email = serializers.SlugRelatedField(read_only=False, slug_field='resource_id')
However, for GET I want to return the embedded objects too, so I could use:
class TopSerializer(serializers.ModelSerializer):
contact = ContactSerializer(read_only=True)
email = EmailSerializers(read_only=True)
So how do I specify in my serializer that contact can be either a slug or a serialized object? Is there a way to do this with just one serializer or must I have two different serializers and use the request.method in the view to select which serializer I use?
Or, should I use something like this:
class TopSerializer(serializers.ModelSerializer):
contact = ContactSerializer(read_only=True)
email = EmailSerializers(read_only=True)
contact_rid = serializers.SlugRelatedField(read_only=False,slug_field=resource_id,queryset=models.Contact.objects.all())
email_rid = serializers.SlugRelatedField(read_only=False,slug_field=resource_id,queryset=models.Email.objects.all())
This way I can use contact_rid and email_rid for POST/PATCH/PUT/DELETE and get contact and email fields back in GET.
Am I on the right track? Other suggestions?
Check out custom fields https://www.django-rest-framework.org/api-guide/fields/#custom-fields
You could define a custom serializer fields that overrides serializers.Field and overrride to_representation to return the fully serialized object and to_internal_value to mimic the behavior of a slugRelatedField.
You are on the right track!
Use one related field for write and another to read the full object is a good approach if you need more details for related objects.
You can also add to the slug field the flag write_only=True if you want the field is used only for write. However, checking this option will not hint selected objects when you are under an update route in Browseable API
Check this anwser

Extending the typer of user the most simple way in Django

I want to create two types of user in Django in the most simple way.
I want to use class AbstractBaseUser
class BaseUser(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
class Service_provider(BaseUser):
company = models.CharField(max_length=140);
def __unicode__(self):
return self.company
class Customer(BaseUser):
name = models.CharField(max_length=140);
def __unicode__(self):
return self.name
I don't know how to pass this two user to the user model without applying any complicated change in the auth model.
Is it possible?
No. Django's built-in auth framework does not support more than one user model. You will need to write your own auth framework from scratch.

Django form on the model

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)

Resources