Django - How to add extra fields to User model? - python

I need to add new fields to the " real Django User model ".
Why? Because I have two forms in my template with post methods in two different pages.
And I created two models, each one saves the corresponding form data in the database.
In my views I had to write two different functions for the forms pages.
The 1st one: when there is a post request, it saves the data in the 1st Model.
The 2nd one: Does the same as 1st but it saves the data in the 2nd Model.
I tried to create another new model3 which contains model1 + model2 fields (Didn't delete the previous models)! But when I submit the 1st form it saves data in an object, and when I submit the 2nd form data in another new object of model3 !
So I canceled this method and now I have to try another way to do the task, So I saved the 1st form data ( which are a login info ( email, pass ) and when a user submits the form, it creates a new user with
user = User.objects.create_user(request.POST.get("email"),request.POST.get("email"),password)
That worked fine, and now I can modify the credentials in the views with just user.username = newemail and user.password with newpassword.. but I couldn't do that with the 2nd form because the User model hasn't as much fields as the Model2! And also when I try it with
data = Model3(fielname = request.POST.get("addressLineForExample")
data.save()
it causes an error saying that I didn't specify for which user id I am going to save it!
I've seen videos and docs about the OneToOneField method! Then I figured out it just shows the model3 fields in the user page in 127.0.0.1:8000/admin, and not adding real fields to the User Model!
I came with the idea of changing user.newaddedfield = any Model3 field! I just want to realize it that way!

You can extend Django's AbstractUser to create your own custom user model on top of Django's User model. For example:
File: project/user/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
custom_field = models.BooleanField(default=False)
Then you need to run
python manage.py makemigrations
python manage.py migrate
in your terminal for creating related model in the database.
In order to see this model in your admin page, register the model using the following snippet:
File: project/user/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
P.S. I strongly recommend adding AUTH_USER_MODEL = "user.User" to project/project/settings.py in order to be able to fully use Django's default User functionalities (including Django Rest Framework's authentication ingtegrations).
P.S. Make sure you have the app's name listed under INSTALLED_APPS in your settings.py

Solution:
I went back with creating another new model3 which contains model1 + model2 fields
Then, when I submit the first form, I do:
data = Model3(field1 = request.POST.get("ValueOfThe1stFormField1")
data.save()
Now the Model3 modem will be filled with the 1st form's data but not yet with the 2nd's.
So in the 2nd function where a user should submit data in the 2nd form, I do an update to the related model3 object like:
Model3.objects.filter(field1=field1OfThe1stForm).update(field2=anything, field3=anything,...)
Hope it helps anyone who is trying to merge two (or more) models in one other model that should contain all of the previous model fields.

Related

Add extra fields to my UserCreationForm from my extended User model

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()

Custom User Model in admin on Django 1.5

I'm using a custom user model myapp.MyUser in a Django 1.5 app. I updated my settings as documentation says to do, AUTH_USER_MODEL = "myapp.MyUser". As MyUser extends AbstractUser, I created the admin with this code:
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
admin.site.register(get_user_model(), UserAdmin)
And it works fine, except the creation form. When I try to create a new user, the following exception is raised:
DatabaseError at /admin/core/user/add/
(1146, "Table 'mydatabase.auth_user' doesn't exist")
The full traceback can be found here.
Digging out Django's source code it looks like UserCreationForm - which is used by UserAdmin - references django's built-in auth.User directly, instead of use get_user_model.
Can it be the problem? Why everything references myapp.MyUser, including admin's auth and the change form, except the creation?
As you say, the UserCreationForm references auth.User directly. The Django docs on custom users and built in auth forms state that you must rewrite it for any custom user model.
UserCreationForm
Depends on the User model. Must be re-written for any custom user model.
There is a related ticket Ticket 20086, which was initially closed as invalid, because the user creation form is working as documented.
There is a full example on the same page, which shows you how to rewrite the forms and register a custom user model in the admin.
If you don't mind to store your custom model in a table called auth_user you can simply set this in Meta and this solves auth_user table doesn't exist. All you need is:
class MyUser(AbstractUser):
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
db_table = 'auth_user'

Django User Profile - Forms

Django 1.4
Sorry if this is a silly question i am fairly new to Django.
I am attempting to link a user and a profile together via the inbuilt auth profile system. All the examples of this i can find do not use a class based view, which is something i would really like to use.
Basically i would like a form that combines the Profile and the User allowing me to create both at the same time. If possible i would like to use the same form to Edit/Create the User + Profile.
I have created a model for the profile: Profile
Created forms:
class UserForm(forms.ModelForm):
class Meta:
model = User
class ProfileRegisterView(FormView):
template_name = 'profile-register-form.html'
form_class = UserForm
success_url = '/account/created/'
Adding the profile to the user model does not seem to include it within the UserForm:
AUTH_PROFILE_MODULE = "creative_profile.Profile"
The 2nd alternative i have tried was to define individual forms in forms.py however the form_class attribute only accepts one form model..
Any pointers help would be great, thanks
One possible solution is to include the Profile fields in your UserForm and override the save() method to populate the Profile fields.
The save() method will have to include a get_or_create() call for the Profile model if you're not using a post_save signal to create it. If you are using a post_save signal to create the Profile model, you're going to have to make sure the User is being saved first before calling the get_profile() method.
I do it in more simple way (i suggest). Just use django build in. In urls.py I added (r'^login/$','django.contrib.auth.views.login'). In settings.py add LOGIN_URL='/login/' and to MIDDLEWARE_CLASSES add 'django.contrib.auth.middleware.AuthenticationMiddleware'. Copy registration/login.html template locally if you want to change it. After such manipulations you will have ability to login as user. Forgot, you also should import from django.contrib.auth.models User and Group.

Django return "Profile matching query does not exist"

I have some issue.
I import django User model, create new user then trying to get it profile, all what I have is "Profile matching query does not exist". Why? I just create the user.
Here is my code:
from django.contrib.auth.models import User
user = User.objects.create(username="stackoverflow", password="tester1234")
user.get_profile()
You might have forgotten to set
AUTH_PROFILE_MODULE
in your settings.py.
The online documentation suggests that get_profile()...
Returns a site-specific profile for this user. Raises django.contrib.auth.models.SiteProfileNotAvailable if the current site doesn't allow profiles, or django.core.exceptions.ObjectDoesNotExist if the user does not have a profile. For information on how to define a site-specific user profile, see the section on storing additional user information below.
Are you sure you've enabled profiles?
From your code snippet it looks like you've perhaps not created a profile which is a separate class (see here.
also write save method in signals.py:
#receiver(post_save,sender=User)
def save_profile(sender,instance,**kwargs):
instance.profile.save()
and also add this in app.py
class UserProfileConfig(AppConfig):
name = 'UserProfile'
def ready(self):
import UserProfile.signals
Django docs define this clearly, I miss that, sorry
Storing additional information about users
If you'd like to store additional information related to your users,
Django provides a method to specify a site-specific related model --
termed a "user profile" -- for this purpose.
To make use of this feature, define a model with fields for the
additional information you'd like to store, or additional methods
you'd like to have available, and also add a OneToOneField named user
from your model to the User model. This will ensure only one instance
of your model can be created for each User. For example:
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
To indicate that this model is the user profile model for a given
site, fill in the setting AUTH_PROFILE_MODULE with a string consisting
of the following items, separated by a dot:
The name of the application (case sensitive) in which the user profile model is defined (in other words, the name which was passed to
manage.py startapp to create the application).
The name of the model (not case sensitive) class.
For example, if the profile model was a class named UserProfile and
was defined inside an application named accounts, the appropriate
setting would be:
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
When a user profile model has been defined and specified in this
manner, each User object will have a method -- get_profile() -- which
returns the instance of the user profile model associated with that
User.
The method get_profile() does not create a profile if one does not
exist. You need to register a handler for the User model's
django.db.models.signals.post_save signal and, in the handler, if
created is True, create the associated user profile:
in models.py
from django.contrib.auth.models import User from
django.db.models.signals import post_save
# definition of UserProfile from above
# ...
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)

Fill a Form on the same page with different classes - write to DB and display values

I have a model with 5 entities and intend to create a form (on the same page) but do not know how to integrate more than one form.
In my main, i can play very well with the forms and write to database, but I need to put more fields on the page.
These fields are of different models.
**
My models:
Teacher, Account(ReferenceProperty), Experience (ReferenceProperty), ServiceDistribution(ReferenceProperty), Experience(ReferenceProperty)
My forms:
class TeacherForm(djangoforms.ModelForm):
class Meta:
model =models.Teacher
exclude = ['user']
and the same for other models
My Main:
class CreateCvHandler(webapp.RequestHandler):
def post(self):
if self.request.get('EscTeacher'):
id = int(self.request.get('EscTeacher'))
teacher=models.teacher.get(db.Key.from_path('Teacher', id))
else:
teacher= models.teacher()
data = forms.TeacherForm(data = self.request.POST)
if data.is_valid():
userList= models.Account.all()
userList.filter('user =', users.get_current_user())
for user in userList:
teacher.user=user.key()
teacher.unity=self.request.get('unity')
teacher.category=self.request.get('category')
teacher.regime=self.request.get('regime')
teacher.put()
self.redirect('/academy')
else:
self.redirect('/createCv')**
Help Please...
If I understood you correctly what you can do is create forms for each model and display them in the template having a single save button. Now when submitted, in your view you can validate each form and add or update the db as required.
Here is a link to an answer to a question similar to what you have asked..
Django: multiple models in one template using forms

Categories

Resources