choices value of select in an inline form in admin django - python

please I want to select the list of cycles by Program_de_bourse, know that in my actual form I can select all the cycles , but I just want to select the cycles linked to Program_de_bourse my foreign key Program_de_bourse = id of Program_de_bourse
the model.py
class Cycle(models.Model):
Programme_de_bourse = models.ForeignKey(Programme_de_bourse, on_delete=models.SET_NULL, null=True)
Objet_programme = models.CharField(
max_length=30,
choices=objet_CHOICES, verbose_name='Cycle'
)
def __str__(self):
return self.Objet_programme
..
class Discipline(models.Model):
Discipline = models.ForeignKey(Disc, on_delete=models.CASCADE, related_name='Discipline_cycle')
Cycle = models.ForeignKey(Cycle, on_delete=models.SET_NULL, null=True)
Programme_de_bourse = models.ForeignKey(Programme_de_bourse, on_delete=models.SET_NULL, null=True,
related_name='Programme_de_bourse_id')
def __str__(self):
return str(self.Discipline)
my admin.py
class Programme_de_bourseAdmin(ExportActionMixin, admin.ModelAdmin):
fieldsets = [
('Programme', {'fields': ['Programme']}),
#'classes': ['collapse']
#
]
list_display = ["Programme",]
inlines = [CycleInline, DisciplineInline, ConditionInline, EtablissementInline, DocumentInline]
class DisciplineInline(ExportActionMixin, admin.TabularInline):
)
model = Discipline
enter image description here

try this
you can create a form for class DisciplineInline and add a filter over there
this might work with some changes
class DisciplineForm(forms.ModelForm):
Programme_de_bourse = forms.ModelChoiceField(queryset='....') # your filter
class Meta:
model = Discipline
fields = ('....')
class DisciplineInline(ExportActionMixin, admin.TabularInline):
model = Discipline
form = DisciplineForm

this is work for me to get cycle by Program_de_bourse_id = 7, now i want replace 7 with real id of Program_de_bourse, so how a can get the id of Program_de_bourse from my function Program_de_bourseAdminrer
class DisciplineForm(forms.ModelForm):
cycle = forms.ModelChoiceField(queryset=Cycle.objects.filter(Programme_de_bourse=7))
class Meta:
model = Discipline
fields = ('cycle','Discipline')

Related

Auto list fields from many-to-many model

I've created a model of analysis types and then I created a table that groups several analyses into one group:
class AnalysisType(models.Model):
a_name = models.CharField(max_length=16,primary_key=True)
a_measur = models.CharField(max_length=16)
a_ref_min = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
a_ref_max = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
# analysis_group = models.ForeignKey(AnalysysGroup, on_delete=models.CASCADE, default=1)
def __str__(self):
return f"{self.a_name} - {self.a_measur}"
class AnalysysGroup(models.Model):
group_name = models.CharField(max_length=32)
analysis = models.ManyToManyField(AnalysisType, blank=True)
def __str__(self):
return f"{self.group_name}"
I want to have the option to multiply add values via the admin panel (I.E. I chose Analysis type then below appear fields to fill)
class PatientGroupAnalysis(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
analysis_date = models.DateTimeField()
analysis_type = models.ForeignKey(AnalysysGroup, on_delete=models.CASCADE, default=1)
# amalysis_data = ???
def __str__(self):
return f"{self.patient}: {self.analysis_date} - {self.analysis_type} - {self.analysis_data}"
I tried to use analysis_data = analysis.type.objects.all() and etc. but that's the wrong way.
Try this:
Admin panel with StackedInline
from django.contrib import admin
from .models import AnalysisType, PatientGroupAnalysis
# Register your models here.
class PatientGroupAnalysisInline(admin.StackedInline):
model = PatientGroupAnalysis
#admin.register(AnalysisType)
class AnalysisTypeAdmin(admin.ModelAdmin):
list_display = ["id", "a_name", "a_measur", "a_ref_min", "a_ref_max"]
search_fields = ("id", "a_name")
inlines = [PatientGroupAnalysisInline]

Showing extra field on ManyToMany relationship in Django serializer

I have a ManyToMany field in Django, like this:
class Dictionary(models.Model):
traditional = models.CharField(max_length=50)
simplified = models.CharField(max_length=50)
pinyin_numbers = models.CharField(max_length=50)
pinyin_marks = models.CharField(max_length=50)
translation = models.TextField()
level = models.IntegerField()
frequency = models.IntegerField()
idiom = models.BooleanField()
child_char = models.ManyToManyField('Dictionary', through='DictionaryChildChar', null=True)
class Meta:
db_table = 'dictionary'
indexes = [
models.Index(fields=['simplified', ]),
models.Index(fields=['traditional', ]),
]
class DictionaryChildChar(models.Model):
class Meta:
db_table = 'dictionary_child_char'
from_dictionary = models.ForeignKey(Dictionary, on_delete=models.CASCADE, related_name="from_dictionary")
to_dictionary = models.ForeignKey(Dictionary, on_delete=models.CASCADE, related_name="to_dictionary")
word_order = models.IntegerField()
Currently, I have a serializer like this:
class FuzzySerializer(serializers.ModelSerializer):
pinyin = serializers.CharField(
required=False, source="pinyin_marks")
definition = serializers.CharField(
required=False, source="translation")
hsk = serializers.CharField(required=False, source="level")
class Meta:
model = Dictionary
fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional", "child_char"]
depth = 1
This gives me a dictionary entry, as well as the child dictionary entries associated with it (as a Chinese word is made up of several Chinese characters)
However, I need to know what order these child characters are in, and hence why I have word_order.
I would like this word_order field to appear on the individual child_char - how do I write my serializer in such a way that this additional field is present? Would I need to make a separate serializer for child_char?
EDIT: I have tried this serializer, it doesn't work:
class FuzzyChildCharSerializer(serializers.ModelSerializer):
class Meta:
model = DictionaryChildChar
fields = ["word_order"]
Easiest way is to create a dedicated FuzzyChildCharSerializer and then connect it to your original serializer as a nested relationship:
class FuzzyChildCharSerializer():
class Meta:
model = DictionaryChildChar
fields = ["word_order"] # And whatever other fields you want
class FuzzySerializer():
child_char = FuzzyChildCharSerializer(many=True)
...
You could also write a SerializerMethodField.
It appears I had to bridge the connection via the glue table, which makes sense.
class FuzzyChildCharSerializer(serializers.ModelSerializer):
pinyin = serializers.CharField(
required=False, source="pinyin_marks")
definition = serializers.CharField(
required=False, source="translation")
hsk = serializers.CharField(required=False, source="level")
class Meta:
model = Dictionary
fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional",]
class FuzzyChildCharSerializerGlue(serializers.ModelSerializer):
to_dictionary = FuzzyChildCharSerializer()
class Meta:
model = DictionaryChildChar
fields = '__all__'
class FuzzySerializer(serializers.ModelSerializer):
pinyin = serializers.CharField(
required=False, source="pinyin_marks")
definition = serializers.CharField(
required=False, source="translation")
hsk = serializers.CharField(required=False, source="level")
from_dictionary = FuzzyChildCharSerializerGlue(many=True)
class Meta:
model = Dictionary
fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional", "from_dictionary"]
depth = 1
This provides each character with its given word order

Adding one to many relationship in Django models

I have two models in my Django-REST application.
a ProjectRequest and a ContactRequest
I want to make it so, each Projectrequest contains a list of the refered Contactrequests.
class ProjectRequest(models.Model):
project_name = models.CharField(max_length=50)
company_name = models.CharField(max_length=50)
#make array of technologiestechnologies = models.ArrayField(base_field=) (blank=True)
project_description = models.CharField(max_length=200)
project_type = models.CharField(max_length=30)
budget_estimation = models.IntegerField(
default=1000,
validators=[
MinValueValidator(1800),
MaxValueValidator(5000000)
])
#time_estimation = models.DateTimeField(default=None, blank=True, null=True)
class ContactRequest(models.Model):
topic = models.CharField(max_length=30)
description = models.CharField(max_length=200)
time = models.CharField(max_length=15)
project_request = models.ForeignKey(ProjectRequest,
on_delete=models.CASCADE)
so far I have established a relationship, with a foreign key, which works fine as of now. However I want to extends the functionality, so, that the ProjectRequest contains a list of all the projectrequest. I have tried with several different fields, without any luck, and the documentation I can only find fields for ManyToMany and OneToOne. How can this be achieved?
There are many ways to achive what you want. For that, lets add a reverse relation in model named contact_requests:
project_request = models.ForeignKey(ProjectRequest, on_delete=models.CASCADE, related_name="contact_requests")
Now you can use PrimaryKeyRelatedField to show Primary Keys of the ContactRequest attached to each ProjectRequest.
class ProjectRequestSerializer(serializers.ModelSerializer):
contact_requests = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = ProjectRequest
fields = ('contact_requests', 'company_name', ...) # other fields
Or if you want all the values of each contact_requests, then you can use nested relationship like this:
class ProjectRequestSerializer(serializers.ModelSerializer):
contact_requests = ContactRequestSerializer(many=True, read_only=True)
class Meta:
model = ProjectRequest
fields = ('contact_requests', 'company_name', ...) # and so on
You could add a property function to the ProjectRequest class that retruns all the ContactRequests that are related to that ProjectRequest like so...
class ProjectRequest(models.Model):
project_name = models.CharField(max_length=50)
company_name = models.CharField(max_length=50)
#make array of technologiestechnologies = models.ArrayField(base_field=) (blank=True)
project_description = models.CharField(max_length=200)
project_type = models.CharField(max_length=30)
budget_estimation = models.IntegerField(
default=1000,
validators=[
MinValueValidator(1800),
MaxValueValidator(5000000)
])
#time_estimation = models.DateTimeField(default=None, blank=True, null=True)
#property
def contact_requests(self):
return ContactRequest.objects.filter(project_request=self)
class ContactRequest(models.Model):
topic = models.CharField(max_length=30)
description = models.CharField(max_length=200)
time = models.CharField(max_length=15)
project_request = models.ForeignKey(ProjectRequest,
on_delete=models.CASCADE)
I had this problem too. This is how I solved it:
ContactRequest= models.ManyToManyField(ContactRequest,related_name="+")

Filtering a django-tables2 table with django-filters using a drop down list

I have a model (Brief) that i am showing in a list with Django-tables2. A Brief can belong to one or many towers. I am trying to create a view where a user can see all briefs, and then filter to find briefs related to a specific tower. I had first implemented this using check boxes, and it was working, but I need to get that filter into a drop down list.
"GET /brief/?towers= HTTP/1.1" - Gives me all the briefs.
"GET /brief/?towers=1 HTTP/1.1" - Gives an empty list of briefs.(should give me 2 in my test data)
Querying in django shell gives me the results I would expect.
Another odd behavior is that my drop down list has spaces that can be selected.
class Attribute(models.Model):
class Meta:
abstract = True
ordering = ['name']
name = models.CharField(max_length=100, unique=True)
created_on = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name='%
(class)s_created_by', null=True, blank=True,
on_delete=models.SET_NULL)
modified_dt = models.DateTimeField(auto_now=True)
modified_by = models.ForeignKey(User, related_name='%
(class)s_modified_by', null=True, blank=True,
on_delete=models.SET_NULL)
def __str__(self):
return self.name
class Tower(Attribute):
pass
class Brief (Attribute):
link = models.URLField()
sources = models.ManyToManyField(SourceSystem)
format = models.ForeignKey(ReportFormat, on_delete=models.PROTECT)
towers = models.ManyToManyField(Tower)
type = models.ForeignKey(ReportType, on_delete=models.PROTECT)
project = models.ForeignKey(Project, on_delete=models.PROTECT)
def tower_list(self):
return ", ".join([str(obj) for obj in self.towers.all()])
def source_list(self):
return ", ".join([str(obj) for obj in self.sources.all()])
My tables.py:
class BriefTable(tables.Table):
name = tables.LinkColumn('brief_detail', args=[A('pk')])
class Meta:
model = Brief
template_name = 'django_tables2/bootstrap.html'
sequence = ('id', 'name', 'type', 'project', 'format',)
exclude = ('link', 'created_on', 'created_by', 'modified_dt', 'modified_by', 'info')
My filters.py
class BriefFilter(django_filters.FilterSet):
towers=django_filters.ModelMultipleChoiceFilter(
queryset=Tower.objects.all(), widget=forms.Select)
class Meta:
model = Brief
fields = ['towers']
my view:
class FilteredBriefListView(LoginRequiredMixin, SingleTableMixin,
FilterView):
table_class = BriefTable
template_name = 'brief/brief_list.html'
paginate_by = 20
filterset_class = BriefFilter
finally my route:
urlpatterns = [
path('', FilteredBriefListView.as_view(), name="home"),
]
After taking a little break I realized I'm using ModelMultipleChoiceFilter with a single choice instead of ModelChoiceFilter... /facepalm.

How to display a foreign key value instead of the id?

I have the following models :
class FlightSchedule(models.Model):
tail_number = models.ForeignKey(TailNumber, null=False)
flight_number = models.CharField(max_length=30, null=False)
flight_group_code = models.ForeignKey(FlightGroup, null=False)
origin_port_code = models.ForeignKey(Port, null=False, related_name="Origin")
destination_port_code = models.ForeignKey(Port, null=False, related_name="Destination")
flight_departure_time = models.TimeField()
start_date = models.DateField()
end_date = models.DateField()
def __unicode__(self):
return u'%s' % self.flight_number
class Meta:
verbose_name_plural = "Flight Schedule"
class FlightScheduleDetail(models.Model):
flight_date = models.CharField(max_length=30, null=False)
flight_number = models.ForeignKey(FlightSchedule, null=False, related_name="flight_number_schedule")
route_id = models.CharField(max_length=30, null=False, unique=True)
flight_status = models.ForeignKey(Status, null=True, default=1)
def __unicode__(self):
return u'%s' % self.route_id
class Meta:
verbose_name_plural = "Flight Schedule Details"
and the serializer is as below :
class FlightScheduleDetailSerializer(serializers.ModelSerializer):
class Meta:
model = FlightScheduleDetail
fields = '__all__'
class FlightScheduleSerializer(serializers.ModelSerializer):
flight_number_schedule = FlightScheduleDetailSerializer(many=True)
class Meta:
model = FlightSchedule
fields = ['tail_number', 'flight_number', 'origin_port_code', 'destination_port_code', 'flight_departure_time',
'flight_number_schedule']
Here tail_number , flight_number is a foreign key. When I create an API, I get the response as the id of the fields. How can I display the name in the json?
My views.py is as below :
#api_view(['GET'])
def flight_schedule(request):
schedule = FlightSchedule.objects.all()
serializer = FlightScheduleSerializer(schedule, many=True)
return Response(serializer.data)
You can define the source with field_name in your serializer as follows.
I have used source='TailNumber.number'. Please use the right field_name in place of number
class UserProfileSerializer(serializers.ModelSerializer):
tail_number = serializers.CharField(source='TailNumber.number', read_only=True)
flight_number = ....(change as above)
class Meta:
model = FlightSchedule
fields = ['tail_number', 'flight_number', 'origin_port_code', 'destination_port_code', 'flight_departure_time',
'flight_number_schedule']
You could simply add them as if they were attributes.
flight_number_str = serializers.ReadOnlyField(source='flight_number.flight_number')
First flight_number is the attribute of FlightScheduleDetail, then the one of FlightSchedule
and then add it to the list of fields fields = [..., 'flight_number_str']
Otherwise you may have a look at nested relationships in DRF which can offer more possibilities also.
Another alternative is to use the depth option in a serializer. It is to specify nested serialization - doc
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
depth = 1
If users is a foreign key or manytomany key the serializer will display the users as an object and not as a key.
The depth option should be set to an integer value that indicates
the depth of relationships that should be traversed before reverting
to a flat representation.

Categories