Store the current user in a field of a django model - django

I'm trying to find the way of store the user who creates an object and I want to do it automatically. I've found some things but nothing works for me. Here is the code:
Models.py:
class Track(models.Model):
...
usuari = models.ForeignKey(User)
Forms.py:
class TrackForm(forms.ModelForm):
class Meta:
model = Track
Views.py
def pujar_track(request):
if request.method=='POST':
formulari = TrackForm(request.POST, request.FILES)
if formulari.is_valid():
formulari.save()
return HttpResponseRedirect('/inici')
else:
formulari = TrackForm()
return render(request,'principal/trackForm.html',
{'formulari':formulari})
I've seen about put:
usuari = models.ForeignKey(User, blank=True, editable=False) but
But I don't know when can I set the user in the field.
Thanks in advice!

You can hide usuari from your TrackForm, so the user can't select it:
class TrackForm(forms.ModelForm):
class Meta:
model = Track
exclude = ('usuari',)
And then, replace your formulari.save() with:
track = formulari.save(commit=False)
track.user = request.user
track.save()
This is a common use case and detailed in the Django docs.

Related

How to save multiple django form in one page with one submit button

i'm new when developing django. I have some question after days by days finding the answer. Here the go.
What i want is making ajax form that handle 2 model form, with 1 submit button
I can already saved the data in each form, but got problem in foreign key field got None instead
Here we go my model:
class ModelA(models.Model):
name = models.CharField(max_length=100, blank=True)
info = models.CharField(max_length=200, blank=True)
def __str__(self):
return self.name
class ModelB(models.Model):
xmodel = models.ForeignKey(to=ModelA, on_delete=models.CASCADE, related_name='modelX', blank=True, null=True)
no_1 = models.CharField(max_length=150, blank=True)
no_2 = models.CharField(max_length=150, blank=True)
Form Class:
class ModelAForm(forms.ModelForm):
class Meta:
model = ModelA
fields = '__all__'
class ModelBForm(forms.ModelForm):
class Meta:
model = ModelB
exclude = ('xmodel',)
View class:
def AddData(request):
tpl = 'add.html'
if request.method == 'POST':
mdla = ModelAForm(request.POST)
mdlb = ModelBForm(request.POST)
if mdla.is_valid():
obj = mdla.save()
if mdlb.is_valid():
mdlb.save(commit=False)
mdlb.xmodel=obj
mdlb.save()
else:
mdla = ModelAForm()
mdlb = ModelbForm()
In TPL i'm using ajax to send, it can save model a and model b, but in modelb xmodel (foreign key) it got None when check in adminpanel.
Which i do wrong, how to make it happen when handling the forms?
For people that got something like me, using 2 form.
i've solved my problem with this logic.
Create object manually
Initiatite form with instance new object
save
for above problem:
def AddData(request):
tpl = 'add.html'
if request.method == 'POST':
mdla = ModelAForm(request.POST)
if mdla.is_valid():
obj = mdla.save()
newObj = ModelB.objects.create(xmodel=obj)
mdlb = ModelBForm(request.POST, instance=newObj)
if mdlb.is_valid():
mdlb.save()
else:
mdla = ModalAForm()
mdlb = ModalBForm
This is solution i get, if anyone could do better please tell me. Thankx

Autofill my author field with foreign key

I am trying to autofill my user foreign key in my note project with authentication in django. I tried, but it's not working and asking that owner is required field. Please, help! Thanks in an advance.
views.py
#login_required(login_url='login')
def index(request):
tasks = Task.objects.filter(owner=request.user)
form = TaskForm()
if request.method=='POST':
form = TaskForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.owner = request.user
instance.save()
context = {
'tasks':tasks,
'form':form,
}
return render(request, 'list.html',context)
models.py
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.title
Since you fill in the owner yourself, it makes no sense to specify the owner as a form field. You thus should exclude it, and let this be handled by the view. The form thus looks like:
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ['owner']
If no ModelForm will need to specify the owner, you can mark the field as non-editable:
class Task(models.Model):
# …
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
# …

How to use a submit a one-to-many form

I have a list of employees who work at a site. Each site is owned by a User (using Django's standard user model).
I want to create a form that adds an employee and automatically links them to a site dependent on who the authenticated user is:
models.py:
class Employee(models.Model):
site = models.ForeignKey(Site, null=True)
employee_name = models.CharField(default='name', max_length=128, blank=False, null=False)
class Site(models.Model):
user = models.ForeignKey(User)
site_name = models.CharField(max_length=128, blank=False, null=False)
views.py:
site_profile = Site.objects.get(user=request.user)
if request.method == "POST":
form = EmployeeAddForm( request.POST )
if form.is_valid():
obj = form.save(commit=False)
obj.site = site_profile
obj.save()
return redirect('dashboard_home')
form = EmployeeAddForm()
return render(request, "dashboard/employees.html", {'form': form })
forms.py:
class EmployeeAddForm(forms.ModelForm):
class Meta:
model = Employee
fields = ( 'employee_name')
This code will add the employee to the database, but in django admin, list_display = 'site' results in Site object not the actual site name. It does not appear that the employee is linked to the site.
If I use obj.site = site_profile.id (adding .id), I get the error Cannot assign "1": "Employee.site" must be a "Site" instance.
Found the error: the above code is correct, I simply had a tab ordering error in my Site modeL
class Site(models.Model):
...
def __str__(self):
return self.site_name
def should have been inserted 1 tab inwards.

Django Hidden Foreign Key in form using Meta model

I am working on a cookbook website using django and have run into a problem with a foreign key field in my form
the problem is that when i create my recipe i need to have a foreign key pointing to the cookbook that created this recipe but I don't want the user creating the recipe to see the original_cookbook field (they shouldn't have to)
I believe I need to use a widget (HiddenInput) but am I getting confused with the examples given on other sites. Also my friend mentioned something about setting an initial value in the original_cookbook view
tl;dr: I want to point the fk to the users cookbook while keeping the original_cookbook field hidden.
relevant code:
form:
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
model:
class Recipe(models.Model):
def __unicode__(self):
return self.name
original_cookbook = models.ForeignKey(Cookbook)
#cookbooks = models.ManyToManyField('Cookbook', related_name = 'recipes')
name = models.CharField(max_length=200)
author = models.CharField(max_length= 100)
picture = models.ImageField(upload_to = 'Downloads', blank=True)
pub_date = models.DateTimeField('date published', auto_now_add=True, blank=True)
ingredients = models.TextField()
steps = models.TextField()
prep_time = models.IntegerField()
TYPE_CHOICES= (
('SW', 'Sandwich'),
('AP', 'Appetizers'),
('SD', 'Sauces and Dressings'),
('SS', 'Soups and Salads'),
('VG', 'Vegetables'),
('RG', 'Rice, Grains and Beans'),
('PA', 'Pasta'),
('BR', 'Breakfast'),
('MT', 'Meat'),
('SF', 'Seafood'),
('BP', 'Bread and Pizza'),
('DT', 'Desserts'),
)
type = models.CharField(max_length = 2, choices=TYPE_CHOICES)
def index_queryset(self):
return self.objects.all()
view:
def createrecipe(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/index/')
else:
if request.method == 'POST':
form = RecipeForm(request.POST)
if form.is_valid():
recipe = form.save()
user = request.user
cookbooks = user.cookbooks
cookbook = cookbooks.all()[0]
cookbook.recipes.add(recipe)
return HttpResponseRedirect('/account')
else:
form = RecipeForm()
return render_to_response('cookbook/createrecipe.html',
{'form':form},
context_instance=RequestContext(request))
Add exclude = ('original_cookbook',) to your form's Meta class.
Then, in your if form.is_valid() code, do something like:
....
recipe = form.save(commit=False)
recipe.original_cookbook = whatever_that_is
recipe.save()
...
This is answered in the documentation.
from django import forms
class RecipeForm(forms.ModelForm):
class Meta:
model = Recipe
widgets = {'cookbook': forms.HiddenInput

How to save a ManyToMany relationship from a ModelForm in Django

I'm not sure to save my ManyToMany relationship. I found my exact problem in this thread: Django embedded ManyToMany form, except instead of Sales and Products models, I have models that make up a movie.
I tried the solution, but I receive a syntax error. I don't understand how Django should link the EquipmentModel, LightModel, and ActorModel to the ManyToMany relationship in MovieModel. So far (before trying the other thread's solution), the CharFields that are displayed on the form for LightModel, EquipmentModel, and ActorModel are not linked to the ManyToManyField in MovieModel. So when I save the forms and try to access a particular Movie's actors, all I see is a blank list. The solution from the other thread seems to make sense since it tries to link the models to the ManyToMany relationship in MovieModel, but I don't understand how Django knows which MovieModel to add to (how does it get the correct movieID?).
On a side note, is there a way to check for duplicate movies when the user presses the 'Submit' button on the form? I want to avoid creating duplicates.
views.py:
def add_movie(request, movieID=""):
if request.method == "POST":
form = MovieModelForm(request.POST)
eform = EquipmentModelForm(request.POST)
lform = LightModelForm(request.POST)
aform = ActorModelForm(request.POST)
print 'checking form'
print request.POST.items()
if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
print 'form is valid'
movie_to_add = form.save()
e = eform.save()
l = lform.save()
a = aform.save()
movie_to_add.actors.add(a)
movie_to_add.lights.add(l)
movie_to_add.equipments.add(e)
# return HttpResponseRedirect('/data')
else:
# code for create forms ....
return render_to_response('add_movie.html', {'form':form, 'eform':eform,'lform':lform, 'aform':aform,}, context_instance=RequestContext(request))
Other code that may help:
forms.py
class LightModelForm(forms.ModelForm):
class Meta:
model = LightModel
class ActorModelForm(forms.ModelForm):
class Meta:
model = ActorModel
class EquipmentModelForm(forms.ModelForm):
class Meta:
model = EquipmentModel
class MovieModelForm(forms.ModelForm):
class Meta:
model = MovieModel
fields = ("title", "rank")
models.py
class EquipmentModel(models.Model):
equip = models.CharField(max_length=20)
class ActorModel(models.Model):
actor = models.CharField(max_length=20)
class LightModel(models.Model):
light = models.CharField(max_length=20)
class MovieModel(models.Model):
rank = models.DecimalField(max_digits=5000, decimal_places=3)
title = models.CharField(max_length=20)
equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
actors = models.ManyToManyField(ActorModel, blank=True, null=True)
lights = models.ManyToManyField(LightModel, blank=True, null=True)
def __str__(self):
return self.title
Edit: removed unnecessary init and fields thanks to DTing
Edit2: Fixed!
There is a whole lot of stuff going wrong here in addition to what spulec said.
Your models.py look okay.
class EquipmentModel(models.Model):
equip = models.CharField(max_length=20)
class ActorModel(models.Model):
actor = models.CharField(max_length=20)
class LightModel(models.Model):
light = models.CharField(max_length=20)
class MovieModel(models.Model):
rank = models.DecimalField(max_digits=5000, decimal_places=3)
title = models.CharField(max_length=20)
equipments = models.ManyToManyField(EquipmentModel, blank=True, null=True)
actors = models.ManyToManyField(ActorModel, blank=True, null=True)
lights = models.ManyToManyField(LightModel, blank=True, null=True)
def __str__(self):
return self.title
You don't need to override the __init__ method on forms if you are not changing anything on init. You also don't need to be explicit about the fields if you want to include them all.
class LightModelForm(forms.ModelForm):
class Meta:
model = LightModel
class ActorModelForm(forms.ModelForm):
class Meta:
model = ActorModel
class EquipmentModelForm(forms.ModelForm):
class Meta:
model = EquipmentModel
class MovieModelForm(forms.ModelForm):
class Meta:
model = MovieModel
fields = ("title", "rank")
your view doesn't really make sense unless for every movie you are trying to add you also want to:
add a new movie to the db using the submitted post data
create one actor object and add to db
create one light object and add to db
create one equipment object and add to db
take those three objects and add them to another movie's m2m relationships.
This other movie is some movie that you pulled from the urlconf and passed to your view, not the one you just created.
This all seems a little strange.
what i think you want to do is create all the equipment, actors and lights objects so they are in your db already, and use the default m2m formfield widget to select them when adding a movie.
so:
forms.py
class MovieModelForm(forms.ModelForm):
class Meta:
model = MovieModel
urls.py:
url(r'^add_movie/$', add_movie)
views.py:
def add_movie(request):
if request.method=='POST':
form = MovieModelForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse('success')
else:
form = MovieModelForm()
context = {'form':form }
return render_to_response('some_template.html', context,context_instance=RequestContext(request))
you could combine adding actors, lights, and equipment into the same form but that's a bit much for me to write out right now.
As far as modifying your original code to add those lights, actors, and equipment to the movie you just created, you could do this:
if form.is_valid() and eform.is_valid() and lform.is_valid() and aform.is_valid():
new_movie = form.save()
e = eform.save()
l = lform.save()
a = aform.save()
new_movie.actors.add(a)
new_movie.lights.add(l)
new_movie.equipments.add(e)
Change it to:
movie_to_add = get_object_or_404(MovieModel, id=movieID)