I need two extra fields for the user data so I followed the official django docs Extending the existing User model, the admin form for users works fine but I have a UserCreationForm and I want to add the two extra fields in that form too, already tried to use two forms, the UserCreationForm and the form for my extended user model but I can't get the id of the UserCreationForm to fill the user_id of my extended user model so I search how to use a signal to do that like the django docs recommend and find this Django Signals: create a Profile instance when a new user is created but that only fill the user_id of my extended user model that is the OneToOneField but not the two extra fields.
sorry for my bad english.
I need to run but here's a quick implementation. It needs some tweaks apparently but should get you started:
# this is your model form for extended OneOnOne with user
class ExtendedForm(forms.ModelForm):
model = ExtendedModel
# temporary exclude user field to pass the validation
exclude = ('user')
def create_user(request):
user_form = UserForm(request.POST or None)
extra_form = ExtendedForm(request.POST or None)
if user_form.is_valid() and extra_form.is_valid():
# create a new user first
new_user = user_form.save()
# create an object in memory but not save it
new_extended_obj = extra_form.save(commit=False)
# assign the user to the extended obj
new_extended_obj.user = new_user
# write to database
new_extended_obj.save()
Related
What would be the steps to create a user profile other than the administrator user please, I am a newbie. I leave the model class of which I want to be a user profile
from django.contrib.auth.models import User
user = models.OneToOneField(User, ondelete=models.CASCADE)
Add this field to the model.
If you are using Django's auth user registration form then, while registering new user in views.py:
form = UserRegistrationForm(request.POST)
if form.is_valid():
instance = form.save()
apoderado = Apoderado()
apoderado.user = instance
apoderado.other_fields = form.cleaned_data['other_fields']
apoderado.save()
This will create new user with extra fields. This is a simple trick but, if any error occurs then only half of data will be stored. If you want to go for extra, use Django signals.
I've got a Django view in charge of showing a user profile. I'm using the user model provided by django itself but I also would like to extend it with some of my own information, So I made my own model to extend the user model itself:
class UserProfile(AbstractBaseUser):
is_verified = models.BooleanField(default=True)
current_profile = models.ImageField(default=static('img/default_profile.jpg'))
ratings = models.ManyToManyField(Video, through='UserProfileVideoRating', related_name='ratings')
views = models.ManyToManyField(Video, through='UserProfileVideoView', related_name='views')
CommentRating = models.ManyToManyField(Comment, through='UserProfileCommentRating', related_name='CommentRating')
subscriptions = models.ManyToManyField(User)
And here is my view I'd like to use for that:
User = get_user_model()
# Create your views here.
class profileDetailView(DetailView):
template_name = 'profile.html'
def get_object(self):
username = self.kwargs.get("username")
if username is None:
raise Http404
return get_object_or_404(User, username__iexact=username, is_active=True)
Now my question is, seeing as DetailViews are meant for a single model, How can I achieve this?
You're confused between two ways of extending the built-in User model.
If you're inheriting from AbstractBaseUser, that means you're defining your own user model - you would need to define its own username/email fields etc, and set the AUTH_USER_MODEL to point to your replacement model. In this case, you wouldn't need to reference two models in your template because your model would be the User.
However if you want to define a related UserProfile, you don't need to inherit from AbstractBaseUser, and you don't need to change AUTH_USER_MODEL; but you do need to define a relation with the actual User model, probably via a one-to-one field. In this case, to get access to the profile you just follow the relationship in the template - eg via {{ user.userprofile.currentprofile }} etc.
In your case I would advise taking the second option; remove the inheritance from AbstractBaseUser and add a one-to-one field to User.
I'm attempting to use a custom inline form within the django admin.
admin.py --
class EmpInline(admin.StackedInline):
model = Emp
form = UpdateYearlyForm
show_change_link = True
class CompanyAdmin(admin.ModelAdmin):
list_display = ('companyname','companyid','get_active', 'get_updated')
inlines = [EmpInline]
When the Company name is clicked on, the company details are shown along with a formset for all the related employees.
This works in regards to displaying the form however one of the fields is a custom choice field which indirectly updated a model field. Which, in the normal user view (this form needs to be used both by an admin for all records and for users for the records pertaining to them) the custom field is handled as below.
I've only shown a snippet of the view as it is quite long.
views.py --
if formset.is_valid():
for form in formset.forms:
if form.is_valid():
obj = form.save(commit=False)
data = form.cleaned_data
if data['updatefield'] == 'accident':
obj.years += 1
else data['updatefield'] == 'free':
obj.years += 1
obj.save()
Is there a way of handling the form (and the custom field) in the same way when used as an inlineform in the admin?
If it helps anyone - overriding the save() function on the form itself sorted this problem and it probably better practice therefore I changed to using this on both the User and Admin side.
I have a problem and I'm looking for the answer like a week ago without finding any.
I want to save a model, using the Django User as a foreign key, I tried creating a new user like this:
user=User.objects.create_user(username, email, password)
And then put the entire user or the user id and does not work, just like this:
studio_form.user_id=user
studio_form.user_id=user.id
And nothing happens, everything is saved in the database, the user, the group, but not the user as a foreign key, the foreign key user_id is null every single time, help please.
so, this is my code:
Django Model:
from django.contrib.auth.models import User
class Studios(models.Model):
user_id=models.ForeignKey(User)
studio_name=models.CharField(max_length=250)
Django Forms:
from django import forms
from web.models import *
class studioForm(forms.ModelForm):
class Meta:
model = Studios
exclude=('user_id')
widgets = {
'password': forms.PasswordInput(),
}
Django View:
def studio_register(request):
if request.method == "POST":
studio_form=studioForm(request.POST, request.FILES)
if studio_form.is_valid():
studio_form.save(commit=False)
data=request.POST
username=data.get("user_name")
email=data.get("email")
password=data.get("password")
user=User.objects.create_user(username, email, password)
group=Group.objects.get(name='studio')
group.user_set.add(user)
studio_form.user_id=user.id
studio_form.save()
Any idea?
You are passing your data back to the studio_form here:
def studio_register(request):
# other view code
studio_form.user_id=user.id
studio_form.save()
You actually need to pass the data to the Studios model in order to save it to the database. The Form is only for cleaning data and temporary holding it until you access the model to save the data to the database.
So if here is you model:
from django.contrib.auth.models import User
class Studios(models.Model):
user_id=models.ForeignKey(User)
studio_name=models.CharField(max_length=250)
You need access it in your view:
def studio_register(request):
# other view code
studio = Studios.objects.create(user_id=user, studio_name=name)
That will create a Studios object, saving the data to the database.
user_id needs to be a User object (not the user.id) since it is a foreign key to the User model. So once you get the user object, then just set the user_id in your Studios model equal to the user. A better naming convention, however, would be to name the field "user" (in order to avoid confusion):
class Studios(models.Model):
user = models.ForeignKey(User)
Make sure that you save studio_name as well because it is a required field in your Studios model.
I've been doing it the other way around user.groups.add(group) maybe that will work for you?
I came across this code:
drinker/models.py:
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class Drinker(models.Model):
user = models.OneToOneField(User)
birthday = models.DateField()
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
drinker/forms.py:
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from drinker.models import Drinker
class RegistrationForm(ModelForm):
username = forms.CharField(label=(u'User Name'))
email = forms.EmailField(label=(u'Email Address'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
password1 = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))
class Meta:
model = Drinker
exclude = ('user',)
def clean_username(self):
username = self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("That username is already taken, please select another.")
def clean(self):
if self.cleaned_data['password'] != self.cleaned_data['password1']:
raise forms.ValidationError("The passwords did not match. Please try again.")
return self.cleaned_data
My Question is about the inner class meta which as two attributes:
model=Drinker
exclude=('user`,)
I have a not-so-clear understanding of how this meta class work. I have read the documentation but I am still confused. Can you kindly explain what those two lines mean and what their purpose is?
Thanks
The exclude attribute tells Django what fields from the model not to include in the form.
Quoting the Selecting fields to use section of the model form documentation:
2. Set the exclude attribute of the ModelForm’s inner Meta class to a list of fields to be excluded from the form.
The model line simply tells Django what model to take the fields from; together the two lines tell Django to give RegistrationForm fields based on all fields on the Drinker model, except 'user'. For the given Drinker model, that's birthday and name.
These fields are added to the other form fields already defined on the form. If the Drinker model gained more fields, those would automatically be part of the form too.
See the Overriding the default fields section of the same chapter:
When you explicitly instantiate a form field like this, it is important to understand how ModelForm and regular Form are related.
ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.
The inner Meta class is just a convenient way to create a namespace for such configuration on your form class for the Django framework to find. All Django now has to do is introspect Form.Meta and see what attributes are defined there.
Note that using exclude can lead to security problems. From the same documenation:
It is strongly recommended that you explicitly set all fields that should be edited in the form using the fields attribute. Failure to do so can easily lead to security problems when a form unexpectedly allows a user to set certain fields, especially when new fields are added to a model. Depending on how the form is rendered, the problem may not even be visible on the web page.
The alternative approach would be to include all fields automatically, or blacklist only some. This fundamental approach is known to be much less secure and has led to serious exploits on major websites (e.g. GitHub).
fields = exclude() and fields = '__all__' - means display all the fields
exclude = ('password',) - means exclude password field
fields = ('user','email',) - means display only email field and userfield
in short : fields you want to show up in the form should be mentioned in 'fields' attribute ex:
fields = '__all__' #will show all the fields from the model in the form
'exclude' does the opposite
exclude = ['title'] # don't show the title field