DJANGO - Models.Forms - Usuarios - django

I'm trying to save and retrive the data owned by the user.
I mean, in one Sqlite3 DB I store the tables for all users but each one has their one data store in it, how can I give each one their own data.
this are my models, view and form
MODEL.PY
class Cuentas (models.Model):
rubro_cta = models.ForeignKey(TipoC, on_delete=models.CASCADE, verbose_name = u'Tipo')
sub_rubro_cta = models.ForeignKey(Sub_rubro, on_delete=models.CASCADE, verbose_name = u'Sub Rubro')
titulo_cuenta = models.CharField(max_length=50)
detalle_cuenta = models.CharField(max_length=60)
importe_cuenta = models.FloatField()
def save(self, *args, **kwargs):
self.importe_cuenta = round(self.importe_cuenta, 2)
super(Cuentas, self).save(*args, **kwargs)
def __str__(self):
return self.detalle_cuenta
FORMS.PY
class CuentasForm (forms.ModelForm):
class Meta:
model = Cuentas
fields = ['rubro_cta', 'sub_rubro_cta', 'detalle_cuenta', 'importe_cuenta']
labels = {
'rubro_cta': _('Cuenta'),
'sub_rubro_cta': _('Tipo'),
'detalle_cuenta': _('Detalle'),
'importe_cuenta': _('Importe'),
}
VIEWS.PY
#login_required
def carga (request):
if request.method == 'POST':
form = CuentasForm(request.POST)
if form.is_valid:
form.save()
return redirect('balance')
else:
form = CuentasForm()
return render (request, "ProyetoWebApp/carga.html",{"form": form})

you have to add a foreign key field to user in your Cuentas class:
class Cuentas (models.Model):
user = models.ForeignKey(User, models.CASCADE)
...
in your view add this code for GET method:
info = None
if request.method == 'GET':
info = Cuentas.objects.get(user=request.user)
return render (request, "ProyetoWebApp/carga.html",{"form": form, "info":info})

Related

Django forms: how to show only objects associated with user in dropdown

I am a vet hospital, with class Pet and class Records. Each pet can have many records, i.e. everytime it visits the hospital it gets a new record.
At the moment, my form shows all the pets ever associated with my app (please view https://i.stack.imgur.com/8j7V8.png).
I want only the user's registered pets to appear (why would Bob be bringing a stranger's cat to the vet?)
View to add a record:
#login_required(login_url="/accounts/login/")
def record_create(request):
#this line retrieves Pets only belonging to the user logged in
pets = Pet.objects.filter(author=request.user)
if request.method == 'POST':
form = forms.CreateRecord(request.POST, request.FILES)
print(form)
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return redirect('records')
else:
form = forms.CreateRecord()
return render(request, 'records/record_create.html', {'form': form,})
forms.py
class CreateRecord(forms.ModelForm):
class Meta:
model = models.Record
fields = ['feedID', 'amountLeftOver', 'amountDispensed', 'additionalInfo', 'selectPet']
models.py
class Pet(models.Model):
petName = models.CharField(max_length=100, default='My Pet')
petImage = models.ImageField(default='default.png', blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.petName
class Record(models.Model):
feedID = models.AutoField(primary_key=True)
dateTime = models.DateTimeField(auto_now_add=True)
amountLeftOver = models.IntegerField(default='0')
amountDispensed = models.IntegerField(default='0')
additionalInfo = models.TextField(default=" ")
selectPet = models.ForeignKey(Pet, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
How do I get the selectPet dropdown to show only Bob's registered pets?
Thanks for your time!
You can override the __init__() method of your form to pass in extra arguments, in this case, you can pass in a user instance, and set the queryset for the dropdown widget.
(Not sure about how you have related the Pet model to the User model, the example below assumes you have a foreign key)
class CreateRecord(forms.ModelForm):
class Meta:
model = models.record
fields = ['feedID', 'amountLeftOver', 'amountDispensed', 'additionalInfo', 'selectPet']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
user = self.kwargs.get('user')
if user:
self.fields['selectPet'].queryset = user.pet_set.all()
Another way to resolve this problem
View to add a record:
#login_required(login_url="/accounts/login/")
def record_create(request):
#this line retrieves Pets only belonging to the user logged in
pets = Pet.objects.filter(author=request.user)
if request.method == 'POST':
form = forms.CreateRecord(request.POST, request.FILES)
print(form)
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return redirect('records')
else:
form = forms.CreateRecord()
form.fields["category"].queryset=Record.objects.filter(user=request.user)
return render(request, 'records/record_create.html', {'form': form,})

Django modelforms, foreignkey filter for data owned by logged in user [duplicate]

I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .

Using existing template for form(showing not all fields)

The issue is next: I'm using existing templates for my site. I have an order page. I want to use my own template for form
I know that I can implement it just using {% for field in form %}. But I need to show not all fields. For example, here is my Order model:
class Order(models.Model):
state_choices = ('ACTIVE', 'COMPLETED', 'FROZEN')
order_date = models.DateTimeField(auto_now_add=True)
delivery_time = models.CharField(max_length=100)
address_city = models.CharField(max_length=40)
address_street = models.CharField(max_length=40)
address_building = models.CharField(max_length=40)
state = models.CharField(max_length=200, default='ACTIVE')
client = models.ForeignKey(CustomUser)
I need to show just: address_city, address_street, address_building and delivery_time. Because in view I just return current user and set it to client. Here is my view that saves Order:
def submit(request):
args = {}
args['form'] = OrderForm
if request.POST:
order_form = OrderForm(request.POST)
if order_form.is_valid():
order_form.save()
user = request.user
address_country = order_form.cleaned_data['address_country']
address_city = order_form.cleaned_data['address_city']
address_building = order_form.cleaned_data['address_building']
delivery_time = order_form.cleaned_data['delivery_time']
new_order = Order(address_country=address_country,
address_city=address_city,
address_building=address_building,
delivery_date=delivery_time, client=user)
new_order.save()
Basket.objects.filter(client=user).delete()
return redirect('/order/')
else:
return render(request, 'order_page.html', args)
I guess that new_order is odd, because order_form.save() saves it. But how to set user of current session to Order through form?
To understand it all, here is my OrderForm code:
class OrderForm(forms.ModelForm):
class Meta():
model = Order
fields = ['address_city', 'address_street', 'address_building', 'delivery_time']
I handle this kind of logic in the form's init method, and when creating the form in the view I pass in the request object as a kwarg for the form to get its data from, then hide the appropriate fields:
In forms.py...
class YourForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
request = kwargs.pop('request', None)
super(YourForm, self).__init__(*args, **kwargs)
if request:
self.fields['field'].initial = process_request_to_get_value(request)
self.fields['field'].widget = forms.HiddenInput()
# More logic here if needed
class Meta:
model = Order
In views.py...
def your_view(request):
if request.method == 'POST':
form = YourForm(request.POST, request = request)
if form.is_valid():
form.save()
return HttpResponseRedirect('somewhere')
else:
form = YourForm(request = request)
return render_to_response('template',
{'form': form,},
context_instance = RequestContext(request))

Filter select field in ModelForm by currently logged in user

I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .

saving django ManyToMany not valid

I have a form from my model that needs to be validated and saved making use of ManyToMany Fields.
Everytime I try and save it, I get thrown back to the page, just saying this field is required
My models.py
class HuntingReport(models.Model):
user = models.ForeignKey(User, related_name='User')
outfitter = models.ForeignKey(User, related_name='Outfitter', null=True, blank=True)
date_travel_started = models.DateField(blank=True, null=True)
date_travel_ended = models.DateField(null=True, blank=True)
title = models.CharField(max_length=50)
report = models.TextField()
wish_list = models.ManyToManyField(Specie)
bag_list = models.ManyToManyField(Trophies)
def __unicode__(self):
return self.title
My forms.py looks as follows
class HuntingReportForm(ModelForm):
date_travel_started = forms.DateField(widget=extras.SelectDateWidget(years=range(1970,2010)))
date_travel_ended = forms.DateField(widget=extras.SelectDateWidget(years=range(1970,2010)))
wish_list = forms.ModelMultipleChoiceField(queryset=Specie.objects.all(), widget=FilteredSelectMultiple("verbose name", is_stacked=False))
bag_list = forms.ModelMultipleChoiceField(queryset=Trophies.objects.all(), widget=FilteredSelectMultiple("verbose name", is_stacked=False))
class Meta:
model = HuntingReport
exclude = ['user']
def __init__(self, user, *args, **kwargs):
super(HuntingReportForm, self).__init__(*args, **kwargs)
users = User.objects.filter(userprofile__outfitter=True)
self.fields['outfitter'].choices = [('', '')] + [(user.pk, user.get_full_name()) for user in users]
my views.py
def create(request, template_name='reports/new.html'):
if request.method == 'POST':
form = HuntingReportForm(request.POST, request.FILES)
if form.is_valid():
newform = form.save(commit=False)
newform.user = request.user
newform.save_m2m()
return HttpResponseRedirect('/hunting-reports/')
else:
form = HuntingReportForm(request.user)
context = { 'form':form, }
return render_to_response(template_name, context,
context_instance=RequestContext(request))
Did you try passing blank=True for model field's constructor, or required=False for the ModelMultipleChoiceField's constructor?
I know that blank=True solves the problem for the form in the admin panel, but I don't know how it gets mapped to the ModelForm's fields. I'm assuming that it gets mapped to required property.