Many to many in django Admin - django

I want to ask. Can i create multiple view my items in django admin.
I have a many to many relationship, so i created an associative entity. But i can't understand how view this in django admin. Can someone help me.
models.py
from django.db import models
from django.contrib import admin
class Client(models.Model):
f_name = models.CharField(verbose_name = "Фамилия", max_length = 100)
l_name = models.CharField(verbose_name = "Имя", max_length = 100)
m_name = models.CharField(verbose_name = "Отчество", max_length = 100)
phone = models.CharField(verbose_name = "Телефон", max_length = 100)
city = models.CharField(verbose_name = "Город", max_length = 100)
address = models.CharField(verbose_name = "Адрес", max_length = 200)
def __str__(self):
return self.f_name + " " + self.l_name + " (" + self.phone + ")"
class Item(models.Model):
name = models.CharField(verbose_name = "Название", max_length = 100)
TYPE_ITEMS = (
("shirt", "Футболка"),
("shoes", "Обувь"),
("bags", "Рюкзаки и сумки"),
("heads", "Головные уборы"),
("others", "Другое"),
)
type_item = models.CharField(verbose_name = "Тип продукта",
choices = TYPE_ITEMS, max_length = 6,
default = "shirt")
other = models.TextField("другая информация")
color = models.CharField("Цвет(а)", max_length = 100)
cost = models.IntegerField("Стоимость за штуку", default = 0)
is_available_now = models.BooleanField("Есть ли в наличии?",
default = False)
available_count = models.IntegerField("Количество в наличии", default = 0)
photo = models.ImageField("Фото", upload_to = "media")
def __str__(self):
return self.name + " " + self.color + " (" + str(self.cost) + " грн)"
class Order(models.Model):
id_client = models.ForeignKey(Client, null = True, blank = True,
verbose_name = "Клиент")
date_order = models.DateField(verbose_name = "Дата заказа")
date_taken = models.DateField(verbose_name = "Дата получения")
is_paid = models.BooleanField(verbose_name = "Оплачено?", default = False)
is_taken = models.BooleanField(verbose_name = "Получил покупатель?",
default = False)
class Order_item(models.Model):
id_order = models.ForeignKey(Order)
id_item = models.ForeignKey(Item)
admin.py
admin.site.register(Item)
admin.site.register(Order)
admin.site.register(Client)
admin.site.register(Order_item)
If user creates order, how can i view what he buy?
If user in admin selects an order i want to view many items. Can i create this with django admin ?

I have done this job. So this is my code:
admin.py
from django.contrib import admin
from myapp.models import Client, Item, Order, Ordering
class ClientAdmin(admin.ModelAdmin):
list_display = ("f_name", "l_name", "m_name", "phone", "city", "address")
list_filter = ["f_name", "l_name", "city"]
class ItemAdmin(admin.ModelAdmin):
list_display = ("name", "type_item", "color", "cost", "is_available_now",
"available_count")
list_filter = ["name", "type_item", "color", "cost", "available_count"]
class OrderingAdmin(admin.ModelAdmin):
list_display = ("id_order", "id_item", "count_items")
list_filter = ["id_order", "id_item", "count_items"]
class OrderingInline(admin.TabularInline):
model = Ordering
fk_name = "id_order"
max_num = 1
class OrderAdmin(admin.ModelAdmin):
list_display = ("id", "id_client", "date_order", "date_taken", "is_paid",
"is_taken")
list_filter = ["date_order", "date_taken", "is_paid", "is_taken"]
inlines = [
OrderingInline,
]
admin.site.register(Item, ItemAdmin)
admin.site.register(Order, OrderAdmin)
admin.site.register(Client, ClientAdmin)
admin.site.register(Ordering, OrderingAdmin)
And what I take:
Thanks to all)))

Instead of use Order_item class, you should add a items = models.ManyToManyField(Item) field into your current Order class.

Related

filter on related_set in Django query

class Hardware(models.Model):
date = models.PositiveSmallIntegerField()
node = models.ForeignKey('Node', on_delete=models.CASCADE,null = True)
slot = models.PositiveSmallIntegerField(null = True)
server = models.CharField(max_length=20,null = True)
server_state = models.CharField(max_length=20,null = True)
adapter = models.CharField(max_length=20,null = True)
adapter_state = models.CharField(max_length=20,null = True)
class Meta:
unique_together = ('date', 'node','slot')
order_with_respect_to = 'node'
def __str__(self):
return self.node.name +" " + self.server
class Node(models.Model):
name = models.CharField(max_length = 40, primary_key = True)
def __str__(self):
return self.name
def inventory_by_node(request):
day = (arrow.now().day) - 1
nodes = Node.objects.prefetch_related("hardware_set").all()
return render(request, 'automation/inventory_by_node.html',{'nodes':nodes})
I need to filter hardware_set based on date which is equal to currrent day. I tried
nodes = Node.objects.prefetch_related(Prefetch("hardwares", quesryset=Hardware.objects.filter(date=day)).all()
but It didn't works says no Pretch is defined
Try this:
prefetch = Prefetch("hardware_set", queryset=Hardware.objects.filter(date=day))
nodes = Node.objects.prefetch_related(prefetch).all()

Django UpdateView and ChoiceField issue. Django 1.11 python 3.6

I am facing a strange problem while implementing ChoiceField and UpdateView in django. I have made a small clip showing the problem that I am facing. Please watch it with subtitles/cc enabled. It will give an idea about the problem I am facing. https://youtu.be/M36TnlJvrZs. The problem goes like this.....
During CreateView, I set the 'gender' ChoiceField as 'Female'. But in UpdateView it pre-populates the 'gender' ChoiceField as Male.
However, The ListView renders the 'gender' field properly as 'Female'.
And strangely, the django admin panel, displays no value at all for the 'gender' field.
Here are all the codes:
models.py:
from django.db import models
from django.core.urlresolvers import reverse
gender_choices = (('Male', 'Male'), ('Female', 'Female'))
class Birth(models.Model):
full_name = models.CharField(max_length = 100)
gender = models.CharField(max_length=6, choices=gender_choices)
date_of_birth = models.DateField()
place_of_birth = models.CharField(max_length = 50)
mother_name = models.CharField(max_length = 50)
father_name = models.CharField(max_length = 50)
address_at_time_of_birth = models.TextField(max_length = 500)
permanent_address = models.TextField(max_length = 500)
registration_no = models.CharField(max_length = 50)
remarks = models.CharField(max_length = 200)
registration_date = models.DateField()
issue_date = models.DateField()
def get_absolute_url(self):
return reverse('birth:birth_update', kwargs={'pk':self.pk})
#return reverse('birth:birth_home')
def __str__(self):
return self.full_name
forms.py:
from django import forms
from .models import *
class BirthForm(forms.ModelForm):
full_name = forms.CharField()
gender = forms.ChoiceField(choices = gender_choices, widget=forms.Select())
date_of_birth = forms.DateField(widget = forms.DateInput(attrs = {'placeholder':'DD/MM/YYYY'}))
place_of_birth = forms.CharField()
mother_name = forms.CharField()
father_name = forms.CharField()
address_at_time_of_birth = forms.CharField(widget = forms.Textarea())
permanent_address = forms.CharField(widget = forms.Textarea())
registration_no = forms.CharField(required = False)
registration_date = forms.DateField(required = False, widget = forms.DateInput(attrs = {'placeholder':'DD/MM/YYYY'}))
remarks = forms.CharField(required = False)
issue_date = forms.DateField(required = False, widget = forms.DateInput(attrs = {'placeholder':'DD/MM/YYYY'}))
class Meta:
model = Birth
fields = '__all__'
views.py:
from django.views.generic import ListView, CreateView, UpdateView
from .models import *
from .forms import *
from datetime import date
class BirthHome(ListView):
template_name = 'birth/birth_home.html'
model = Birth
context_object_name = 'birth_objects'
paginate_by = 20
def get_queryset(self):
return Birth.objects.all().order_by('-id')
class NewBirth(CreateView):
model = Birth
form_class = BirthForm
#fields = '__all__'
template_name = 'birth/birth_add.html'
def form_valid(self, form):
obj = form.save(commit = False)
if not obj.registration_date:
obj.registration_date = date.today()
if not obj.issue_date:
obj.issue_date = date.today()
if not (date(1900, 1, 1) <= obj.date_of_birth <= date.today()):
form.add_error('date_of_birth', 'Please enter a valid date')
return super(NewBirth, self).form_invalid(form)
obj.full_name = obj.full_name.upper()
obj.gender = obj.gender.upper()
obj.place_of_birth = obj.place_of_birth.upper()
obj.mother_name = obj.mother_name.upper()
obj.father_name = obj.father_name.upper()
obj.address_at_time_of_birth = obj.address_at_time_of_birth.upper()
obj.permanent_address = obj.permanent_address.upper()
if obj.remarks:
obj.remarks = obj.remarks.upper()
self.object = form.save()
return super(NewBirth, self).form_valid(form)
class BirthUpdate(UpdateView):
model = Birth
form_class = BirthForm
template_name = 'birth/birth_update.html'
def form_valid(self, form):
obj = form.save(commit = False)
if not obj.registration_date:
obj.registration_date = date.today()
if not obj.issue_date:
obj.issue_date = date.today()
if not (date(1900, 1, 1) <= obj.date_of_birth <= date.today()):
form.add_error('date_of_birth', 'Please enter a valid date')
return super(BirthUpdate, self).form_invalid(form)
obj.full_name = obj.full_name.upper()
obj.gender = obj.gender.upper()
obj.place_of_birth = obj.place_of_birth.upper()
obj.mother_name = obj.mother_name.upper()
obj.father_name = obj.father_name.upper()
obj.address_at_time_of_birth = obj.address_at_time_of_birth.upper()
obj.permanent_address = obj.permanent_address.upper()
if obj.remarks:
obj.remarks = obj.remarks.upper()
self.object = form.save()
return super(BirthUpdate, self).form_valid(form)
I searched a lot and experimented a lot as well, but to no avail. Seriously need help. Also if this approach is not correct, what should be the correct working approach??
Solved!
So after lots of experimenting, I realized what the problem was!! It was in models.py file:
Since, I was converting all my inputs to uppercase, the 'choices' tuple also needed to have the values in uppercase. Initially the gender_choices tuple read like this:
gender_choices = (('Male', 'Male'), ('Female', 'Female'))
And in my views, I was making the gender as uppercase, thus causing mis-match in the declared tuple data and form data.
So, I changed the tuple to this:
gender_choices = (('MALE', 'MALE'), ('FEMALE', 'FEMALE'))
Works like a Charm!! Cheers.... And thanx for all the help and suggestions. Any feedback is always welcome :)

django-select2 not working with inlines in django-admin

Here are my models and admin classes:
---------------------Models-----------------------
from django.contrib.auth.models import User
class PurchaseOrder(models.Model):
buyer = models.ForeignKey(User)
is_debit = models.BooleanField(default = False)
delivery_address = models.ForeignKey('useraccounts.Address')
organisation = models.ForeignKey('useraccounts.AdminOrganisations')
date_time = models.DateTimeField(auto_now_add=True)
total_discount = models.IntegerField()
tds = models.IntegerField()
mode_of_payment = models.ForeignKey(ModeOfPayment)
is_active = models.BooleanField(default = True)
class Meta:
verbose_name_plural = "Purchase Orders"
def __unicode__(self):
return '%s' % (self.id)
----------------------------------Admin----------------------------------------
"""
This class is used to add, edit or delete the details of item purchased
"""
class PurchasedItemInline(admin.StackedInline):
form = ItemSelectForm
model = PurchasedItem
fields = ['parent_category', 'sub_category', 'item', 'qty', ]
extra = 10
class BuyerChoices(AutoModelSelect2Field):
queryset = User.objects.all()
search_fields = ['username__icontains', ]
class BuyerForm(ModelForm):
user_verbose_name = 'Buyer'
buyer = BuyerChoices(
label='Buyer',
widget=AutoHeavySelect2Widget(
select2_options={
'width': '220px',
'placeholder': 'Lookup %s ...' % user_verbose_name
}
)
)
class Meta:
model = PurchaseOrder
fields = '__all__'
"""
This class is used to add, edit or delete the details of items
purchased but buyer has not confirmed the items purchased, this class
inherits the fields of PurchaseOrder derscribing the delivery address of
buyer , is_debit , total discount , tds and mode of payment
"""
class PurchaseOrderAdmin(admin.ModelAdmin):
form = BuyerForm
#list_display = ['id','buyer','delivery_address','date_time','is_active']
inlines = [PurchasedItemInline]
# model = PurchaseOrder
#actions = [mark_active, mark_inactive]
#list_filter = ['date_time']
#search_fields = ['id']
list_per_page = 20
def response_add(self, request, obj, post_url_continue=None):
request.session['old_post'] = request.POST
request.session['purchase_order_id'] = obj.id
return HttpResponseRedirect('/suspense/add_distance/')
I am trying to implement django-select2, but when I use inlines in
PurchaseOrderAdmin it doesn't show the field where I have implemented
django-select2:
But when I remove inlines, it works fine:
Edit
Here is the ItemSelectForm
class ItemSelectForm(forms.ModelForm):
class Media:
js = (
'http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
'js/ajax.js',
)
try:
parent_category = forms.ModelChoiceField(queryset=Category.objects.\
filter(parent__parent__isnull=True).filter(parent__isnull=False))
sub_category_id = Category.objects.values_list('id',flat=True)
sub_category_name = Category.objects.values_list('name',flat=True)
sub_category_choices = [('', '--------')] + [(id, name) for id, name in
itertools.izip(sub_category_id, sub_category_name)]
sub_category = forms.ChoiceField(sub_category_choices)
except:
pass
item = forms.ModelChoiceField(queryset = Product.objects.all())
def __init__(self, *args, **kwargs):
super(ItemSelectForm, self).__init__(*args, **kwargs)
self.fields['parent_category'].widget.attrs={'class': 'parent_category'}
self.fields['sub_category'].widget.attrs={'class': 'sub_category'}
self.fields['item'].widget.attrs={'class': 'item'}
It worked for me by adding the following line in the static/suit/js/suit.js
Add:
(function ($) {
Suit.after_inline.register('init_select2', function(inline_prefix, row){
$(row).find('select').select2();
});

Django foreign key is not set and hence unable to save form

I have a simple foreign key relationship between two tables. I am able to save the parent, but am unable to save the child which has a foreign key to the parent. This is what my models look like:
class Product(models.Model):
month_choices = tuple((m,m) for m in calendar.month_abbr[1:])
year_choices = tuple((str(n), str(n)) for n in range(2004, datetime.now().year +2 ))
id = models.AutoField(primary_key = True)
title = models.CharField(max_length = 1024)
product_type = models.ForeignKey(ProductType)
month = models.CharField(max_length =3, choices=month_choices)
year = models.CharField(choices=year_choices, max_length = 4)
project = models.CharField(max_length = 15, null = True, blank = True)
url = models.URLField(null = True, blank = True)
export_to_xsede = models.BooleanField()
#def __str__(self):
# return str(self.id)
class Meta:
db_table = "product"
class ProductResource(models.Model):
CHOICES = (('A','A'),('B','B'),('C','C'),('D','D'),('E','E'))
id = models.AutoField(primary_key = True)
product = models.ForeignKey(Product)
resource = models.CharField(choices=CHOICES, max_length = 15)
And my views:
class PublicationForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'size':'70'}),required=False)
url = forms.CharField(widget=forms.TextInput(attrs={'size':'70'}),required=False)
class Meta:
model = Product
class ResourceForm(forms.ModelForm):
resource = forms.MultipleChoiceField(choices=ProductResource.CHOICES, widget = forms.CheckboxSelectMultiple)
class Meta:
model = ProductResource
I save the parent:
saved_publication = publications_form.save()
but am unable to save the resource form:
resource_form = ResourceForm(request.POST, instance = saved_publication)
resource_form.product = saved_publication
resource_form.save()
When I print resource_form.errors, I get:
<ul class="errorlist"><li>product<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
I have no idea why the foreign key is not getting set in this case.
I'm assuming you do not want to display the product field on the form, so you should exclude it from the form so the validation will pass:
class ResourceForm(forms.ModelForm):
resource = forms.MultipleChoiceField(choices=ProductResource.CHOICES, widget = forms.CheckboxSelectMultiple)
class Meta:
model = ProductResource
exclude = ['product']
Then in the view, just set the product manually after calling is_valid(). Just be sure to pass commit=False on the form.save() so that it will not actually save to the database until after you set the product. For example
...
saved_publication = publications_form.save()
resource_form = ResourceForm(request.POST)
if resource_form.is_valid():
resource = resource_form.save(commit=False)
resource.product = saved_publication
resource.save()

Django and ModelForm. How to change IntegerField to dropdown box

I have a model that looks like this
class RSVP (models.Model):
def __unicode__(self):
return self.firstName + " " + self.lastName
firstName = models.CharField(max_length=30)
lastName = models.CharField(max_length=30)
rsvpID = models.CharField(max_length=9, unique = True)
allowedAdults = models.IntegerField(default = 2)
allowedChildren = models.IntegerField(default = 0)
adultsAttending = models.IntegerField(default = 0)
childrenAttending = models.IntegerField(default = 0)
and I have a ModelForm that looks like this
class RsvpForm(ModelForm):
class Meta:
model = RSVP
exclude= ('firstName', 'lastName', 'allowedAdults', 'allowedChildren')
What I would like to happen is that instead of a text field for the adultsAttending, a dropdown box with the values 0 to allowedAdults shows up. This is for a wedding rsvp site and I'd like to set the max number of +1's an invitee can bring on an individual basis
Any thoughts on how to go about this?
I'm thinking you want to fork the allowed children/ adults as well as the name to another model:
models.py
class Invited(models.Model):
f_name = models.CharField()
l_name = models.CharField()
allowed_adults = models.IntegerField()
allowed_children = models.IntegerField()
class RSVP(models.Model):
invited = models.ForeignKey(Invited)
adults_attending = models.IntegerField()
children_attending = models.IntegerField()
Then you would create the invited objects and assign the allowed adults and children. And the RSVP form would take those number into account when generating the choices for your drop down box.
The drop down can be implemented by overriding the IntegerField widget with a ChoiceField
forms.py
class InvitedForm(forms.ModelForm):
class Meta:
model = Invited
class RSVPForm(forms.ModelForm):
class Meta:
model = RSVP
exclude = ['invited',]
def __init__(self, *args, **kwargs):
max_adults = kwargs.pop('max_adults',2) #default to 2 if no max set
max_children = kwargs.pop('max_children',2) #default to 2 if no max set
super(RSVPForm, self).__init__(*args, **kwargs)
adult_choices = ( (x,str(x)) for x in range(max_adults+1)) )
children_choices = ( (x,str(x)) for x in range(max_children+1)) )
self.fields['adults_attending'] = forms.ChoiceField(choices = adult_choices)
self.fields['children_attending'] = forms.ChoiceField(choices = children_choices)
views.py
def rsvp_view(request, invited_id):
invited = get_object_or_404(Invited, pk=invited_id)
if request.method=='POST':
form = RSVPForm(request.POST, max_adults=invited.allowed_adults,
max_children=invited.allowed_children)
if form.is_valid():
rsvp = form.save(commit=False)
rsvp.invited = invited
rsvp.save()
return HttpResponse("Success")
else:
form = RSVPForm(max_adults=invited.allowed_adults, max_children=invited.allowed_children)
context = { 'form':form,
'invited':invited }
return render_to_response('rsvp.html', context,
context_instance=RequestContext(request))