how to chain field? - django

This my engine models
from django.db import models
class Colors(models.Model):
color_name = models.CharField(max_length=50)
def __unicode__(self):
return self.color_name
This my Cars models
from django.db import models
class Cars(models.Model):
car_model = models.CharField(max_length=50)
car_colors = models.ManytoManyField(Colors, related_name='Car Colors')
def __unicode__(self):
return self.car_model
O.K. Let's see my CarsData Model.
This my CarsData models
from django.db import models
class CarsData(models.Model):
car_barcode= models.CharField(max_length=50)
available_color = ChainedForeignKey(
Cars,
chained_field="car_model",
chained_model_field="car_colors",
show_all=False,
auto_choose=True
)
def __unicode__(self):
return self.car_barcode
My admin.py looks like that:
from django.contrib import admin
from django import forms
from myapp.models import *
class CarsDataAdminForm(forms.ModelForm):
class Meta:
model = CarsData
def __init__(self, *arg, **kwargs):
super(CarsDataAdminForm, self).__init__(*arg, **kwargs)
self.fields['available_color'].choices = [(csc.id,csc.car_colors) for csc in Cars.objects.all()
class CarsDataAdmin(admin.ModelAdmin):
form = CarsDataAdminForm
admin.site.register(CarsData,CarsDataAdmin)
Is there anyway to show in the ChoiceField 'just' color_name field datas? I see just car_model because i have to set it :
def __unicode__(self):
return self.car_model
How can i chain available_colors field to color_name field? I want to show in available_colors choices just color names like red, blue, black, white...
Can you please give me an example?

I think I don't get your code:
class CarsData(models.Model):
car_barcode = models.CharField(max_length=50)
available_color = ChainedForeignKey(
Cars,
chained_field="car_model", # should be a field in THIS model
chained_model_field="car_colors", # should be the matching field
# in the Cars model
show_all=False,
auto_choose=True
)
And both referenced fields must be ForeignKeys to the same (third) model.
Maybe this works, even without changing the AdminForm (I also changed the model names to singular and remove some repetitions, as the most common use dictates):
class Color(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class CarModel(models.Model):
model = models.CharField(max_length=50)
available_colors = models.ManytoManyField(Color, through='AvailableColor')
def __unicode__(self):
return self.model
class AvailableColor(models.Model):
car_model = models.ForeignKey(CarModel)
color = models.ForeignKey(Color)
def __unicode__(self):
return unicode(self.color)
class CarData(models.Model):
car_barcode = models.CharField(max_length=50)
car_model = models.ForeignKey(CarModel)
car_color = ChainedForeignKey(
AvailableColor,
chained_field="car_model", # field in CarData
chained_model_field="car_model", # field in AvailableColor
show_all=False,
auto_choose=True
)
You can't do otherwise because you need two models with a matching FK. Using Cars.car_colors.through (that is a valid model on which to query etc) you don't have a good display. With a (dummy) explicit intermediate model you define unicode and the admin should show the correct data.

Related

Queryset from non-related model in __init__ modelform method

I have two model classes. They are not related models (no relationship).
# models.py
class Model1(models.Model):
description = models.TextField()
option = models.CharField(max_length=64, blank=False)
def __str__(self):
return self.option
class Model2(models.Model):
name = models.CharField(max_length=64, blank=False)
def __str__(self):
return self.name
I have respective form from where I am submitting and saving data in my table. I want to use my Model2 data to fill-in 'option' field as select field, so I am introducing below init method.
# forms.py
class Model1Form(forms.ModelForm):
def __init__(self, *args, **kwargs):
all_options = Model2.objects.all()
super(Model1Form, self).__init__(*args, **kwargs)
self.fields['option'].queryset = all_options
class Meta:
model = Model1
fields = ('description', 'option')
It does not render the dropdown on my template, so I am wondering whether it is right way to address the issue (acknowledging that models are not related to each other).

Connection of 3 Models with Foreign Key

I am a newbie in Django. I have 3 models: Continent, Country, Region
Here is the code:
from django.db import models
# Create your models here.
class Continent(models.Model):
continent = models.CharField(max_length=50, unique=True)
class Meta:
ordering = ['continent']
def __str__(self):
return self.continent
class Country(models.Model):
country = models.CharField(max_length=50, unique=True)
continent = models.ForeignKey(Continent)
class Meta:
ordering = ['country']
verbose_name_plural = 'Countries'
def __str__(self):
return self.country
class Region(models.Model):
country = models.ForeignKey(Country)
region = models.CharField(max_length=50)
class Meta:
ordering = ['region']
def __str__(self):
return self.region
def get_continent(self):
return self.get_continent()
my admin.py looks like this:
from django.contrib import admin
from location.models import Continent, Country, Region
# Register your models here.
class MyAdmin1(admin.ModelAdmin):
list_display = ['continent']
#list_display_links = None
#actions = None
class MyAdmin2(admin.ModelAdmin):
list_display = ['country', 'continent']
class MyAdmin3(admin.ModelAdmin):
model = Region
list_display = ['region', 'country', 'get_continent']
admin.site.register(Continent, MyAdmin1)
admin.site.register(Country, MyAdmin2)
admin.site.register(Region, MyAdmin3)
But in admin panel when I click on table regions it doesn't show 3 attributes in 3 columns. Please, help.
You get a infinite recursion in the Region.get_continent() method:
class Region(models.Model):
...
def get_continent(self):
return self.get_continent()
Change it to:
def get_continent(self):
return self.country.continent

django ForeignKey model filter in admin-area?

Hi I need really very very simple example. First my models:
#This my student models
from django.db import models
SEX_CHOICES= (
('M', 'Male'),
('F', 'Female'),
)
class Students(models.Model):
student_name = models.CharField(max_length=50)
student_sex = models.CharField(max_length=8, choices=SEX_CHOICES)
student_city = models.Charfield(max_length=50)
student_bio = models.TextField()
def __unicode__(self):
return self.student_name
O.K. Let see my ClassRooms Model.
#This my ClassRooms models
from django.db import models
from myproject.students.models import *
class ClassRooms(models.Model):
class_number= models.CharField(max_length=50)
class_student_cities = models.ForeignKey(Students)
class_year = models.DateField()
def __unicode__(self):
return self.class_number
How can i show in the class_student_cities area the Students.student_city datas? I guess that about django-admin area. When i do it withclass_student_cities = models.ForeignKey(Students) i just see in that area the Students.student_name data (ex: John Smith). I want to see JUST Students.student_cities data (ex: NewYork). Can you give me a little example?
Should i use something like that:
class_student_cities = models.ForeignKey(Students.student_cities)
Many Thanks!
Try redifinition unicode method.
def __unicode__(self):
return self.student_city
So you'll see in the field student city.
Well, I tried to remake your application to set data with forms class. Something like this in admin.py in your application:
from django.contrib import admin
from django import forms
from myapp.models import *
class ClassRoomsAdminForm(forms.ModelForm):
class Meta:
model = ClassRoom
def __init__(self, *arg, **kwargs):
super(ClassRoomsAdminForm, self).__init__(*arg, **kwargs)
self.fields[' class_student_cities'].choices = [(csc.id,csc.student_city) for csc in Students.objects.all()
class ClassRoomsAdmin(admin.ModelAdmin):
form = ClassRoomsAdminForm
admin.site.register(ClassRooms,ClassRoomsAdmin)
Maybe you'll need to fix something, but I hope it will work. You will set init function to your forms, so in admin panel you set all choices to everything you keep in your Students model. csc.id you'll need to make this object iterable (cities aren't unique) and then you can choose everything from Students model to set in the field.

Django Inline Forms newly added Foreign Key Field but not showing in newly added inline rows

I am quite newbie in Django world. My question is I ve two models shown below. It works quite well with Grapelli and inline-sortables. Only problem is whenever I add a new foreign key for "equipment" or "image type" fields. They don't show up in the drop down menu of newly added inline rows. I went through internet but couldn't find a smilar problem and a solution.
I would appreciate some help with this.
My model is:
from django.db import models
from datetime import datetime
from thumbs import ImageWithThumbsField
from positions.fields import PositionField
class Artist(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class ImageType(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class Equipment(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class Image(models.Model):
name = models.CharField(max_length=255)
image_file = models.ImageField(upload_to = "images/%Y-%m-%d")
Image_Type = models.ForeignKey(ImageType)
upload_date = models.DateTimeField('date_published',default=datetime.now)
artist = models.ForeignKey(Artist)
equipment = models.ForeignKey(Equipment)
order = PositionField(collection='artist')
def __unicode__(self):
return self.name
class Meta:
ordering = ['order']
And My admin.py is:
from gallery.models import Image,ImageType,Artist,Equipment
from django.contrib import admin
class ImageUploadAdmin(admin.ModelAdmin):
fields = ['name','artist','equipment','image_file','Image_Type','upload_date']
list_filter = ['upload_date']
date_hierarchy = 'upload_date'
class ImageInline(admin.TabularInline):
model = Image
list_display = ('name','equipment','image_file','Image_Type','upload_date')
sortable_field_name = "order"
exclude = ('upload_date',)
extra = 0
class ArtistAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Artist,ArtistAdmin)
admin.site.register(Image, ImageUploadAdmin)
admin.site.register(ImageType)
admin.site.register(Equipment)

How to show database in django-admin using filters by default?

I need to filter database by default every time that I see it (when I save changes or when I open database first time).
Can anybody tell me how to do it?
This is possible with custom custom Managers:
Say you have a class called Book:
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
And you want the admin pages for book objects to only show books by Roald Dahl, then you can add a custom manager:
class DahlBookManager(models.Manager):
def get_query_set(self):
return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager()
dahl_objects = DahlBookManager()
Then you just need to specify that your ModelAdmin should use the dahl_objects manager, which is explained here.
Here is my models.py:
from django.db import models
class DahlBookManager(models.Manager):
def get_query_set(self):
return super(DahlBookManager, self).get_query_set().filter(processed=False)
class Book(models.Model):
book_name = models.CharField('book',max_length=1000,null=True, blank=True)
url = models.CharField(max_length=1000,null=True, blank=True)
processed = models.BooleanField('Done',)
def __str__(self):
return u'%s' % (self.book_name)
def url1(self):
return '%s' % (self._url, self.url)
site_url1.allow_tags = True
class Admin:
pass
class Meta:
db_table = 'books'
objects = models.Manager()
dahl_objects = DahlBookManager()
here is my admin.py:
from django.contrib import admin
from mybooks.booksdb.models import Book
from django import forms
admin.autodiscover()
class BookAdmin(admin.ModelAdmin):
def queryset(self,request):
qs=self.model.objects.get_query_set()
ordering = self.ordering or ()
if ordering:
qs=qs.order_by(*ordering)
return qs
....
No filter by default. Where is my miss?