I'm creating an inventory management system using django as a framework. I have a simple model with a product column and an order_amount column. The only part I want users being able to update using the modelformset is the order_amount column. Django automatically labels each form with the field name "Order Amount". What I would like it to do is to label each form as the instance it is updating from the Product field.
models.py
class Sysco_Products(models.Model):
Products = models.CharField(max_length = 200)
order_amount = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.Products
class meta:
managed = True
db_table = 'sysco_products'
forms.py
from django import forms
from .models import Sysco_Products
class orderform(forms.ModelForm):
class Meta:
model = Sysco_Products
fields = ('order_amount',)
views.py
class SyscoOrder(TemplateView):
template_name= "SyscoOrder.html"
def get(self, request):
OrderFormSet = modelformset_factory(Sysco_Products, fields=('order_amount',))
context = {
'OrderFormSet' : OrderFormSet,
}
return render(request, self.template_name, context)
def post(self, request):
OrderFormSet = modelformset_factory(Sysco_Products, fields=('order_amount',))
formset = OrderFormSet(request.POST,)
if formset.is_valid():
formset.save()
return redirect('Order')
context ={
'formset' : formset,
}
return render(request, self.template_name, context)
You mean something like field.label = f"{sysco_product_instance.Products} amount:"?
This should work:
from django.utils.translation import gettext
class orderform(forms.ModelForm):
class Meta:
model = Sysco_Products
fields = ('order_amount',)
def __init__(self, *args, **kwargs):
super(self, orderform).__init__(*args, **kwargs)
if self.instance.Products.strip():
self.fields['order_amount'].label = gettext("%(product_name)s amount:").format(product_name=self.instance.Products)
Related
In forms, I am trying to filter marketplace drop down field that belong to the logged in user based on its group. Its listing all the dropdown field items. I tried below but I think something is wrong with the filter part.
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user=self.user)
class Meta:
model = Infringement
class Meta:
ordering = ['-updated', '-created']
def __str__(self):
return self.name
fields = ['name', 'link', 'infringer', 'player', 'remove', 'status',
'screenshot','marketplace']
models.py
class Marketplace (models.Model):
name = models.CharField(max_length=100)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
groups = models.ForeignKey(Group, on_delete=models.CASCADE,default=1)
Try this inside __init__() method:
def __init__(self, user, *args, **kwargs):
self.user = user
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset = Marketplace.objects.filter(groups__user=self.user)
final answer is adding self.user = user in the forms and adding user in the view.
forms.py
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
self.user = user
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user=self.user)
class Meta:
model = Infringement
fields = ['name', 'link', 'infringer', 'player', 'remove', 'status',
'screenshot', 'marketplace']
views.py
#login_required(login_url='login')
def createInfringement(request):
user=request.user
form = InfringementForm(user=request.user)
if request.method == 'POST':
form = InfringementForm(user, request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home') context ={'form': form} return render (request, 'base/infringement_form.html', context)
Try this solution...
Basically groups is foreign key in Marketplace model it returns a full object of the Group model.
you tried to filter with the full object it's not possible in a query, so you can filter using id of the user instance
Code becomes like this
class InfringementForm(ModelForm):
def __init__(self, user, *args, **kwargs):
super(InfringementForm,self).__init__(*args, **kwargs)
self.fields['marketplace'].queryset =
Marketplace.objects.filter(groups__user__id=self.user.id)
class Meta:
model = Infringement
I am trying to have a logged in User fill out a form to create a Group. On Group creation, I need the User to automatically be added to the Group.
For this problem, we are working with two models - User and Group.
User is the default model provided by Django.
Group is defined like so:
class Group(models.Model):
name = models.CharField(max_length=255, unique=True)
admins = models.ManyToManyField(User, default=1, related_name='user_username')
all_users = models.ManyToManyField(User, default=1)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('home')
def get_admins(self):
return ", ".join([u.username for u in self.admins.all()])
def add_admin(self, user):
self.admins.add(user)
def get_all_users(self):
return ", ".join([u.username for u in self.all_users.all()])
def add_user(self, user):
self.all_users.add(user)
self.save()
def is_admin(self, user):
if user in self.admins.all():
return True
else:
return False
And the view I'm trying to refactor is:
#login_required
def user_generated_group(request):
if request.method == 'POST':
form = GroupForm(request.POST)
user = request.user
if form.is_valid():
group = Group.objects.create(name=form.cleaned_data['name'])
group.add_admin(user)
group.add_user(user)
group.save()
return HttpResponseRedirect(reverse('home'))
else:
form = GroupForm()
context = {
'form': form,
'type': 'group',
'sidebar': Sidebar(request),
}
return render(request, 'form.html', context)
Here is the GroupForm:
class GroupForm(forms.ModelForm):
class Meta:
model = Group
fields = '__all__'
exclude = ['all_users', 'admins', ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'input'})
The goal is to utilize Django's built-in CreateView. The refactored view so far looks like:
class CreateGroup(LoginRequiredMixin, CreateView):
model = Group
form_class = GroupForm
template_name = 'form.html'
I have yet to implement the add_user and add_admin logic to this view. The hope is that I can manage these methods elsewhere.
I'm unsure of where to go from here. Should this logic be handled by the User or the Group?
If by the Group, should I be using a Manager?
If by the User, should I create a custom User model?
You can override the form_valid [Django-doc] method, to add the self.request.user to the group, like:
from django.http import HttpResponseRedirect
class CreateGroup(LoginRequiredMixin, CreateView):
model = Group
form_class = GroupForm
template_name = 'form.html'
def form_valid(self, form):
self.object = group = form.save()
group.all_users.add(self.request.user)
return HttpResponseRedirect(self.get_success_url())
I recently was able to figure out how to do this in the CreateView, but the same is not working for the UpdateView (Here's the original post on how to do it in the CreateView: (Django) Limited ForeignKey choices by Current User)
Essentially, I need it to display only the Universes created by the currently logged in user, but by default, it displays all universes.
When I try to set a form_class and have it mimic the solution for CreatView, it spits out an improperly configured error.
models.py:
class Universe(models.Model):
user = models.ForeignKey(User,related_name='universe',on_delete=models.CASCADE)
name = models.CharField(max_length=100, unique=True)
description = models.TextField(max_length=2000,blank=True,default="")
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('universe:singleuniverse',kwargs={'pk': self.pk})
class Meta:
ordering = ['name']
unique_together = ['user','name']
class Character(models.Model):
user = models.ForeignKey(User,related_name='characters',on_delete=models.CASCADE)
universe = models.ForeignKey("story_universe.Universe", on_delete=models.CASCADE)
name = models.CharField(max_length=255,unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('character_developer:singlecharacter',kwargs={'pk': self.pk})
class Meta():
ordering = ['name']
unique_together=['user','name']
views.py:
class UpdateCharacter(LoginRequiredMixin,generic.UpdateView):
model = Character
fields = ('universe','name')
template_name = 'character_developer/character_update_form.html'
UPDATE
The error was:
Error: ImproperlyConfigured at /characters/update/3/
UpdateCharacter is missing a QuerySet. Define UpdateCharacter.model, UpdateCharacter.queryset, or override UpdateCharacter.get_queryset().
and here's what the code looked like to get the error:
views.py:
class UpdateCharacter(LoginRequiredMixin,generic.UpdateView):
template_name = 'character_developer/character_update_form.html'
form_class = UpdateForm
def get_form_kwargs(self):
kwargs = super(UpdateCharacter,self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
forms.py
class UpdateForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
user = kwargs.pop('user')
super(UpdateForm,self).__init__(*args,**kwargs)
self.fields['universe'].queryset = Universe.objects.filter(user=user)
class Meta:
model = Character
fields = ('universe','name')
I believe you need the following in your views.py (almost an exact extension of your CreateCharacter):
class UpdateCharacter(LoginRequiredMixin, generic.UpdateView):
model = Character
template_name ='character_developer/character_create.html'
form_class = UpdateForm
def get_form_kwargs(self):
kwargs = super(UpdateCharacter,self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save
return super().form_valid(form)
I would caveat the above - make sure that the user instance in the request object is that of the currently logged in user, and has sufficient permission to update their own user - and can't somehow make a request on their behalf.
Hi I am having trouble figuring out how to solve this error. I was creating a form to be able to add new topics to a website I am working on. After creating the form and trying to use it to submit a request to add a new topic I got a integrityError which I haven't encountered before. After doing some research I know it has something to do with a foreign key relationship where there is a field that is empty inside the database but I am not sure how to root cause it.
here is my Models.py file:
from django.db import models
# Create your models here.
class Category(models.Model):
"""A category the user is writing about"""
text = models.CharField(max_length=200)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
"""Return a string represtation of the model."""
return self.text
class Topic(models.Model):
"""A topic that is associated with a certain Category"""
category = models.ForeignKey(Category, on_delete=models.CASCADE)
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Topics'
def __str__(self):
"""Return string represtation of the model."""
return self.text
class Entry(models.Model):
"""A entry associated with a certain topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Entries'
def __str__(self):
"""Return string represtation of the model."""
return self.text[:50] + "..."
forms.py
from django import forms
from .models import Category, Topic
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['text']
labels = {'text': ''}
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import Category, Entry, Topic
from .forms import CategoryForm, TopicForm
# Create your views here.
def index(request):
"""The home page for Learning Logs"""
return render(request, 'blogging_logs/index.html')
def categories(request):
"""show all categories"""
categories = Category.objects.all()
context = {'categories': categories}
return render(request, 'blogging_logs/categories.html', context)
def topics(request, category_id):
"""Show all topics for a single category"""
category = Category.objects.get(id=category_id) # get category that was requested
topics = category.topic_set.all() # get all topics associated with category that was requested
context = {'category': category, 'topics': topics}
return render(request, 'blogging_logs/category.html', context)
def topic(request, entry_id):
"""Show entry for single topic"""
topic = Topic.objects.get(id=entry_id)
entries = topic.entry_set.all()
context = {'topic': topic, 'entries': entries}
return render(request, 'blogging_logs/topic.html', context)
def new_category(request):
"""Add a new category"""
if request.method != 'POST':
# No data submitted; create a blank formself.
form = CategoryForm()
else:
# POST data submitted; process data
form = CategoryForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:categories'))
context = {'form': form}
return render(request, 'blogging_logs/new_category.html', context)
def new_topic(request):
""" Add new topic to category """
if request.method != 'POST':
# No data submitted; create a blank formself.
form = TopicForm()
else:
form = TopicForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:topics'))
context = {'form': form}
return render(request, 'blogging_logs/new_topic.html', context)
Any help to point me in the right direction is appreciated thank you!
Select Category
Add new topic to category
class Topic(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
#your other fields
Run python manage.py makemigrations and python manage.py migrate command, the error will be removed.
I'm trying to make inline forms with class based views, i followed the instrunctions from here. The only change i've made was to give self.request.user instead of self.object to instance:
models.py
class Client(models.Model):
user = models.OneToOneField(CustomUser)
translate = models.BooleanField(default=False)
class ClientData(models.Model):
client = models.ForeignKey(Client)
language = models.ForeignKey(Language)
forms.py
class ClientForm(ModelForm):
class Meta:
model = Client
fields = '__all__'
exclude = ['user', ]
class ClientDataForm(ModelForm):
class Meta:
model = ClientData
fields = '__all__'
exclude = ['client', ]
ClientFormSet = inlineformset_factory(Client, ClientData, form=ClientDataForm, extra=1)
views.py
class ClientView(LoginRequiredMixin, UpdateView):
model = Client
fields = '__all__'
success_url = reverse_lazy('core:index')
class ClientDataView(LoginRequiredMixin, UpdateView):
template_name = 'core/client_data.html'
model = ClientData
form_class = ClientDataForm
success_url = reverse_lazy('core:index')
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
def get_context_data(self, **kwargs):
context = super(ClientDataView, self).get_context_data(**kwargs)
if self.request.POST:
context['client_data'] = ClientFormSet(self.request.POST, instance=self.get_object())
else:
context['client_data'] = ClientFormSet(instance=self.get_object())
return context
def form_valid(self, form):
context = self.get_context_data()
client_data = context['client_data']
with transaction.atomic():
self.object = form.save()
if client_data.is_valid():
client_data.instance = self.object
return super(ClientDataView, self).form_valid(form)
Whenever i try to enter the page i get:
ValueError: Cannot query "asd#gmail.com": Must be "Client" instance.
[13/Dec/2017 15:48:36] "GET /client-data/ HTTP/1.1" 500 143759
for this line:
context['client_data'] = ClientFormSet(instance=self.get_object())
Your get_object is returning a ClientData instance.
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
However, as the error suggests, the instance should be a Client instance, for example:
def get_object(self, queryset=None):
profile = get_object_or_404(Client, user=self.request.user)
return profile
Or you can simply follow the one-to-one relation backwards:
def get_object(self, queryset=None):
return self.request.user.client