Need Help in django form widgets - django

I am in a middle of a project. I need help in using widgets. I have a Model for which i want a model form :
My model is :
class Appointments(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
app_time = models.DateTimeField()
diognoses = models.TextField(max_length=1000, null=True, blank=True)
prescriptions = models.TextField(max_length=250, null=True, blank=True)
class Meta:
unique_together = ('doctor', 'patient', 'app_time')
def __str__(self):
st = str(self.patient.user.name)+str(self.doctor.user.name)
return st
The corresponding model form is :
class AppointmentBookForm(forms.ModelForm):
app_time = forms.DateTimeField(widget=forms.SplitDateTimeWidget())
class Meta:
model = Appointments
fields = ['doctor','app_time']
Now for app_time I have split the date and time field which is already working fine.
Now I want a dropdown for date and a suitable widget for time.
The time should contain only hours and minutes.
And Finally I also want to provide the options for timing depending on the date and doctor.

For plain html the easiest way might be to define two input fields, one for the time and one for the date.
Input type="date":
https://www.w3schools.com/tags/att_input_type_date.asp
Input type="time":
https://www.w3schools.com/tags/att_input_type_time.asp
There are multiple results to this, here is one proposal:
models.py
from datetime import datetime
class Appointments(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
time = models.TimeField()
date = models.DateField()
app_time = models.DateTimeField()
diognoses = models.TextField(max_length=1000, null=True, blank=True)
prescriptions = models.TextField(max_length=250, null=True, blank=True)
def save(self, *args, **kwargs):
self.app_time = datetime.combine(self.date, self.time)
super().save(*args, **kwargs)
class Meta:
unique_together = ('doctor', 'patient', 'app_time')
def __str__(self):
st = str(self.patient.user.name)+str(self.doctor.user.name)
return st
forms.py
class AppointmentBookForm(forms.ModelForm):
class Meta:
model = Appointments
fields = ['doctor', 'time', 'date']
"""
# Optional: Define dedicated types or classes for the single fields
widgets = {
'time': forms.DateField(attr={"class": "myclass", "type": "time"})
}
"""
The app_time is quite redundant in this case. You could also define a property to receive the datetime:
class Appointments(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
time = models.TimeField()
date = models.DateField()
diognoses = models.TextField(max_length=1000, null=True, blank=True)
prescriptions = models.TextField(max_length=250, null=True, blank=True)
#property
def app_time(self):
return datetime.combine(date, time)
class Meta:
unique_together = ('doctor', 'patient', 'time', 'date')
def __str__(self):
st = str(self.patient.user.name)+str(self.doctor.user.name)
return st
example:
appointment = Appointments.objects.first()
print(appointment.app_time)
Alternatively, use some nice front end framework if you want to keep a single datetimefield.

Related

DRF: Serialization with cross reference table

I have 3 models, the first one contains controller names and their IDs, the second measurements and their IDs and the third has foreign keys to both and is used as a cross-reference based on IDs.
With the following serializer and view I can have my API return the measurements each controller has.
Serializer:
class MeasurementsSerializer(serializers.ModelSerializer):
# used in stationsMeasurementsInfo view
def create(self, validated_data):
pass
def update(self, instance, validated_data):
pass
class Meta:
model = Measurements
fields = ['code', 'measurement', 'unit', 'type']
View:
class stationsMeasurementsInfo(generics.ListAPIView):
#returns the measurements a station tracks
#authentication_classes = (TokenAuthentication,)
#permission_classes = (IsAuthenticated,)
serializer_class = MeasurementsSerializer
def get_queryset(self):
source = self.kwargs['sourceName']
name = self.kwargs['stationName']
final = Measurements.objects.filter(microcontrollersmeasurements__microcontroller__name=name)
return final
def list(self, request, *args, **kwargs):
res = super(stationsMeasurementsInfo, self).list(request, *args, **kwargs)
res.data = {"source": self.kwargs['sourceName'],
"stations": [{
"station": self.kwargs['stationName'],
"measurements": res.data
}
]
}
return res
The problem is that I cannot actually retrieve the name of the controller, currently, I manually insert it into the list which means that I cannot retrieve the measurements of multiple controllers with a single API call. How would I go about fixing this issue?
EDIT:
Models:
class Microcontrollers(models.Model):
name = models.CharField(max_length=25)
serial_number = models.CharField(max_length=20, blank=True, null=True)
type = models.CharField(max_length=15, blank=True, null=True)
software = models.CharField(max_length=20, blank=True, null=True)
version = models.CharField(max_length=5, blank=True, null=True)
date_installed = models.DateField(blank=True, null=True)
date_battery_last_replaced = models.DateField(blank=True, null=True)
source = models.CharField(max_length=10, blank=True, null=True)
friendly_name = models.CharField(max_length=45, blank=True, null=True)
private = models.IntegerField()
datetime_updated = models.DateTimeField(db_column='DateTime_Updated') # Field name made lowercase.
class Meta:
managed = True
db_table = 'microcontrollers'
verbose_name_plural = "Microcontrollers"
def __str__(self):
return self.friendly_name
class Measurements(models.Model):
code = models.CharField(max_length=30)
measurement = models.CharField(max_length=30)
unit = models.CharField(max_length=25)
type = models.CharField(max_length=25)
datetime_updated = models.DateTimeField(db_column='DateTime_Updated') # Field name made lowercase.
class Meta:
managed = True
db_table = 'measurements'
datetime_updated = models.DateTimeField(db_column='DateTime_Updated') # Field name made lowercase.
class MicrocontrollersMeasurements(models.Model):
microcontroller = models.ForeignKey(Microcontrollers, models.DO_NOTHING, blank=True, null=True)
measurement = models.ForeignKey(Measurements, models.DO_NOTHING, blank=True, null=True)
datetime_updated = models.DateTimeField(db_column='DateTime_Updated') # Field name made lowercase.
class Meta:
managed = True
db_table = 'microcontrollers_measurements'
def __str__(self):
return self.measurement.measurement
First of all I think one-to-many relation between Microcontroller and Measurement would be better for this situation - by logic, you can't have one masurement for many microcontrollers.
Your models names should by singular like Microcontroller, Measurement.
If you still wants to stay with this relations, this solution should work:
Add many to many field to Measurements model.
microcontrollers = models.ManyToManyField(
Microcontrollers,
related_name="measurements",
through='yourapp.MicrocontrollersMeasurements',
through_fields=('measurement', 'microcontroller')
)
Update your MeasurementsSerializer
class MeasurementsSerializer(serializers.ModelSerializer):
...
microcontrollers = MicrocontrollerSerializer(read_only=True, many=True)
class Meta:
model = Measurements
fields = ['code', 'measurement', 'unit', 'type', 'microcontrollers']
Remember to prefetch_related('microcontrollers') for better database query performance.

how to use django Serializer or signal to add object in database?

I create ticket , ticketflow , ticketstate , tickettype models
i need a serializer or signal that when user create ticket programmatically add ticketflow object and set state of ticket to submited or something else
Here is my models
class TicketType(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class TicketState(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class Ticket(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4 , editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket_type = models.ForeignKey(TicketType,on_delete=models.CASCADE , default=1)
title = models.CharField(max_length=255, blank=False, null=False)
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
class TicketFlow(models.Model):
uuid = models.UUIDField(default=uuid4, editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket = models.ForeignKey(Ticket,on_delete=models.CASCADE , related_name='ticketflow')
ticket_state = models.ForeignKey(TicketState,on_delete=models.CASCADE , default=1 , related_name='ticketstate')
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now= True)
class Meta:
ordering = ['-created_on']
here is my serializers
class TicketTypeSerializer(serializers.ModelSerializer):
class Meta:
model = TicketType
fields = ('id','title',)
class TicketStateSerializer(serializers.ModelSerializer):
class Meta:
model = TicketState
fields = ('id','title',)
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = ['id' , 'author', 'ticket_type','title' ,'message' , 'attachment' , 'created_on']
class TicketFlowSerializer(serializers.ModelSerializer):
class Meta:
model = TicketFlow
fields = ['author', 'ticket_state', 'message', 'attachment', 'created_on', 'updated_on']
It'll be great if someone can help me out in this. how can i create signal or override create method in serializers
You probably want your "state" field to be read-only in the serializer, this way it can only be changed programmatically, and in the model set a default value with default='pending'.
Then you can override the update method in a Serializer (see the doc here):
def update(self, instance, validated_data):
validated_data['state'] = 'edited'
return super(MySerializer, self).update(instance, validated_data)

how to have database relationship with the active data. in django

i have some active and non active data's in EVENT models and active data has the VISITORS form to fill ..so far i have tried OnetoOne relationship but it didn't succeed ..i am getting both active and non active field in VISITORs model..thank you for your time.
here is models.py
class Event(models.Model):
event_id = models.AutoField
Event_Name = models.CharField(max_length=50)
description = RichTextField()
date_And_time = models.DateTimeField()
location=models.CharField(max_length=50)
slugs = models.SlugField(max_length= 200,default="")
picture = models.ImageField(upload_to='wildlife/picture', default="")
active = models.BooleanField(default=False)
class Meta:
ordering = ["date_And_time"]
def __str__(self):
return self.Event_Name
class Eventvisitor(models.Model):
event = models.OneToOneField(Event, on_delete=models.CASCADE, related_name="eventvistor",default="")
name = models.CharField(max_length=50)
email = models.CharField(max_length=70, default="")
phone = models.CharField(max_length=20,default="")
date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-date']
def __str__(self):
return self.email
You can limit the choices with limit_choices_to=… [Django-doc]. But likely what you want is a ForeignKey, since otherwise, each Event can have at most one related EventVisitor (a OneToOneField is basically a ForeignKey with a unique=True constraint).
class Eventvisitor(models.Model):
event = models.ForeignKey(
Event,
limit_choices_to={'active': True},
on_delete=models.CASCADE,
related_name='eventvistors'
)
name = models.CharField(max_length=50)
email = models.CharField(max_length=70, default="")
phone = models.CharField(max_length=20,default="")
date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-date']
def __str__(self):
return self.email
Note that while one can only select Events with active=True, if you later set the .active field to False, items will still link to it, since the relation is not enforced at database level.

Django REST: How to filter related set?

I'm trying to create a Serializer which contains cities and for every city list of trips which belongs to the current user. The problem is that I'm getting all trips, not just users ones.
My expectation for example if user was two times in London and once in Prague:
[{<serialized London>,'trips':[<serialized the two London trips>]},
{<serialized Prague>, 'trips':[<serialized one trip to Prague]}]
Now I'm getting all trips connected with the city.
Models:
class City(models.Model):
place_id = models.CharField(max_length=1000, unique=True, null=True, blank=True)
lat = models.DecimalField(max_digits=6, decimal_places=3, db_index=True, null=True, blank=True)
lng = models.DecimalField(max_digits=6, decimal_places=3, db_index=True, null=True, blank=True)
class Trip(models.Model):
user = models.ForeignKey('auth.User', related_name='trips')
city = models.ForeignKey('locations.City', related_name='trips')
date_from = models.DateField(default=now)
date_to = models.DateField(default=now)
detail = models.TextField(null=True, blank=True)
View:
def ajax_get_my_trips(request):
trips = Trip.objects.filter(user=request.user)
cities = City.objects.filter(trips__in=trips)
response = MyCityTripsSerializer(cities,many=True).data
return JsonResponse(response, safe=False)
Serializers:
class MyTripsSerializer(serializers.ModelSerializer):
class Meta:
model = Trip
fields = ('date_from', 'date_to', 'detail')
def get_queryset(self):
user = self.request.user
return Trip.objects.filter(user=user)
class MyCityTripsSerializer(serializers.ModelSerializer):
trips = MyTripsSerializer(many=True)
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address', 'trips')
Do you know how to make it work?
class MyTripsSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all())
city = serializers.PrimaryKeyRelatedField(queryset=City.objects.all())
class Meta:
model = Trip
fields = ('date_from', 'date_to', 'detail')
def get_queryset(self):
user = self.request.user
return Trip.objects.filter(user=user)
class MyCityTripsSerializer(serializers.ModelSerializer):
trips = MyTripsSerializer(many=True)
class Meta:
model = City
fields = ('place_id', 'lat', 'lng', 'number_of_users_here_now', 'formatted_address', 'trips')
class Trip(models.Model):
user = models.ForeignKey('auth.User', related_name='user_trips')
city = models.ForeignKey('locations.City', related_name='trips')
date_from = models.DateField(default=now)
date_to = models.DateField(default=now)
detail = models.TextField(null=True, blank=True)
Related name must be unique for every ForeignKey.

Tricky issue passing data from form to form in django

I am a django newbie and have one more big struggle for longer time... :/
User can choose a 'main language' which is set as ForeignKey. User can choose 'further languages' as ManyToMany (Checkbox). Assuming, user selects english as 'main' language, so english has to be filterd out from the 'further languages'... have been searching so much and have no idea how to do it. Is this even possible without JavaScript?
Of course, I could set the 'queryset' in the second form but it would filter the objects after the submit... The similar problem is, when a selected country has to be connected to the proper zipcodes...
I am very thankful for any hints.
Best regards.
class Country(models.Model):
enter code here
country = models.CharField(max_length=40)
active = models.BooleanField(default=True)
class Meta:
verbose_name_plural = 'Länder'
def __str__(self):
return self.country
class ZipCode(models.Model):
zipcode = models.CharField(max_length=5)
city = models.CharField(max_length=255)
active = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'Postleitzahlen'
def __str__(self):
return '{0} {1}'.format(self.zipcode, self.city)
class MainLanguage(models.Model):
language = models.CharField(verbose_name='Hauptsprache', max_length=40)
active = models.BooleanField(default=True)
class Meta:
verbose_name_plural = 'Hauptsprachen'
ordering = ['language']
def __str__(self):
return self.language
class SecondLanguage(models.Model):
language = models.CharField(verbose_name='weitere Sprachen', max_length=40)
active = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'weitere Sprachen'
ordering = ['language']
def __str__(self):
return self.language
class CustomUserprofile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(verbose_name='Vorname', max_length=40,
null=True, blank=True)
country = models.ForeignKey(Country, verbose_name='Land',
null=True, blank=True)
zipcode = models.ForeignKey(ZipCode, blank=True, null=True)
main_language = models.ForeignKey(
MainLanguage, verbose_name='Hauptsprache',
null=True, blank=True)
second_language = models.ManyToManyField(
SecondLanguage, verbose_name='weitere Sprachen',
null=True, blank=True)
class UserProfileForm(forms.ModelForm):
second_language = forms.ModelMultipleChoiceField(
queryset=SecondLanguage.objects.all(),
required=False,
widget=forms.CheckboxSelectMultiple)
class Meta:
model = CustomUserprofile
exclude = ('user',)