Django Models create a task for all users - python

I'm trying to build a webapp where the same task is given to all users, and when the users complete the task they can mark it as completed, to do so I added a 'status' bool that is set to true when the 'task' is not complete, and with a button the user can set it to false, the problem is that when I use a many-to-many field, if one user changes the 'status', it changes for everyone.
I also tried using a Foreignkey but when I use a Foreignkey I have to create a task for every user.
What I want is to create a task, assign it to all users, and then all the users can interact with the task without affecting what other users see.
These are the models that I created(it's in spanish):
class Usuario(AbstractUser):
pass
class Tps(models.Model):
users = models.ForeignKey(Usuario, on_delete=CASCADE)
titulo = models.CharField(max_length=100)
TECNOLOGIA_DE_LA_FABRICACION = 'TDF'
MANTENIMIENTO_Y_REPARACION_DE_EQUIPOS = 'MYRDE'
MAQUINAS_ELECTRICAS_Y_ENSAYOS = 'MEYE'
SEGURIDAD_E_HIGIENE_INDUSTRIAL = 'SEHI'
LABORATORIO_DE_ENSAYOS_INDUSTRIALES = 'LDEI'
INSTALACIONES_INDUSTRIALES = 'II'
RELACIONES_HUMANAS = 'RH'
TALLER_DE_ELECTROMECANICA = 'TE'
ORGANIZACION_INDUSTRIAL = 'OI'
INSTALACIONES_ELECTRICAS = 'IE'
EDUCACION_FISICA = 'EF'
EQUIPOS_Y_APARATOS_DE_MANIOBRA_Y_TRANSPORTE = 'EYADMYT'
MATERIAS_CHOICES = [
(TECNOLOGIA_DE_LA_FABRICACION, 'Tecnologia de la fabricación'),
(MANTENIMIENTO_Y_REPARACION_DE_EQUIPOS, 'Mantenimiento y R de equipos'),
(MAQUINAS_ELECTRICAS_Y_ENSAYOS, 'Máquinas eléctricas y ensayos'),
(SEGURIDAD_E_HIGIENE_INDUSTRIAL, 'Seguridad e higiene industrial'),
(LABORATORIO_DE_ENSAYOS_INDUSTRIALES,
'Laboratorio de ensayos industriales'),
(INSTALACIONES_INDUSTRIALES, 'Instalaciones industriales'),
(RELACIONES_HUMANAS, 'Relaciones humanas'),
(TALLER_DE_ELECTROMECANICA, 'Taller de electromecánica'),
(ORGANIZACION_INDUSTRIAL, 'Organización industrial'),
(INSTALACIONES_ELECTRICAS, 'Instalaciones eléctricas'),
(EDUCACION_FISICA, 'Educacion fisica'),
(EQUIPOS_Y_APARATOS_DE_MANIOBRA_Y_TRANSPORTE,
'Equipos y aparatos de maniobra y transporte')
]
materia = models.CharField(
max_length=8, choices=MATERIAS_CHOICES, default=None)
fecha_actual = models.DateField(default=timezone.now)
fecha_entrega = models.DateField(auto_now=False, auto_now_add=False)
material = models.URLField()
consignas = models.URLField()
status = models.BooleanField(default=True)
def __str__(self):
return self.titulo

I think you should use an intermediate table and make the relationship with the through attribute, so you could make a table like this:
class Tps(models.Model):
users = models.ForeignKey(Usuario, on_delete=CASCADE, through='TaskDone')
class TaskDone(models.Model):
user = models.ForeignKey(Usuario, on_delete=models.CASCADE)
tps = models.ForeignKey(Tps, on_delete=models.CASCADE)
status = models.BooleanField(default=True)

Related

Django REST: ignoring custom fields which are not part of model

My TimeReport model looks like this:
class TimeReport(models.Model):
minutes_spent = models.PositiveIntegerField()
task = models.ForeignKey(Task, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
reported_for = models.DateField()
note = models.TextField(null = True, blank=True)
status = models.CharField(max_length=50, choices=State.choices, default=State.new)
user = models.ForeignKey(User, on_delete=models.PROTECT)
And my model serializer:
class TimeReportCreateSerializer(serializers.ModelSerializer):
class Meta:
model = TimeReport
fields = (
'id',
'minutes_spent',
'reported_for',
'note',
'status',
'task_custom_id',
)
task_custom_id = serializers.CharField()
def create(self, validated_data):
user = User.objects.get(auth_user_id = self.context['user_id'])
task = Task.objects.filter(custom_id = validated_data['task_custom_id']).filter(user = user.id).first()
report = TimeReport(**validated_data)
report.user = user
report.task = task
report.save()
return report
So, the problem is, that I want to take a custom value in a serializer, which is not a part of a model and do some custom logic with it - in this case search for the right 'task' in the database. But when I try to parse the model by using report = TimeReport(**validated_data), it gives me an exception:
TypeError at /api/report/
TimeReport() got an unexpected keyword argument 'task_custom_id'
Im kind of new to Django and python itself, so - what is the best approach?
If you are going to use that field only for creation, you should use write_only option.
task_custom_id = serializers.CharField(write_only=True)
See the docs here https://www.django-rest-framework.org/api-guide/fields/#write_only
You just need to remove task_custom_id from the dictionary
class TimeReportCreateSerializer(serializers.ModelSerializer):
class Meta:
model = TimeReport
fields = (
'id',
'minutes_spent',
'reported_for',
'note',
'status',
'task_custom_id',
)
task_custom_id = serializers.CharField()
def create(self, validated_data):
user = User.objects.get(auth_user_id = self.context['user_id'])
task_custom_id = validated_data.pop("task_custom_id")
task = Task.objects.filter(custom_id = task_custom_id).filter(user = user.id).first()
report = TimeReport(**validated_data)
report.user = user
report.task = task
report.save()
return report
task = Task.objects.filter(custom_id = validated_data.pop('task_custom_id')).filter(user = user.id).first()
the **validated_data will return (task_custom_id=value, field1=value1 ...) and task_custom_id it's not a TimeReport field so all u need is to pop it from validated_data before calling the constructor TimeReport

Django model form field to have a user dropdown list based on a condition

In a Django Modelform (Product_definition), i want to have a dropdown(Merchant name) which will show users only if the their designation in User form is "Merchant".
is it possible that I could get the list of users for the dropdown based on this condition .Please note that i don't require it to be a foreign key as connecting the models is not required.
This is the form which contains the Designation :
from django.contrib.auth.models import User
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete = models.CASCADE)
#extra UserAttribute
MERCHANT = 'MR'
FABRIC = 'FR'
WASHING = 'WS'
PRINT = 'PR'
PLANNER = 'PL'
DESIGNATION_CHOICES =(
(PLANNER,'Planner'),
(MERCHANT,'Merchant'),
(FABRIC,'Fabric'),
(WASHING,'Washing'),
(PRINT,'Printing'),
)
Designation =models.CharField(
max_length = 20,
choices = DESIGNATION_CHOICES,
default= 'PLANNER'
)
def __str__(self):
return self.user.username
and this is the form with Merchant Name where I want the names of all merchants to appear.
class Product_definition(models.Model):
Order_number = models.CharField(max_length=25,unique = True, blank = True, null = True)
style_name = models.CharField(max_length=15, blank = True, null = True)
color = models.CharField(max_length=15, blank = True, null = True)
Order_qty = models.PositiveIntegerField()
SMV = models.FloatField()
MERCHANT = models.ForeignKey(UserProfileInfo,on_delete= models.CASCADE,default='Select')
def __str__(self):
return self.Order_number
I have created a foreign key for now but I don't require it and it doesn't list the names of only the merchant in the drop down.
I think you can do it like this using ModelChoiceField:
class ProductForm(forms.ModelForm): # please use CamelCase when defining Class Names
MERCHANT = forms.ModelChoiceField(queryset=UserProfileInfo.objects.filter(Designation=UserProfileInfo.MARCHENT)) # Please use sname_case when naming attributes
class Meta:
model = Product_definition # Please use CamelCase when defining model class name
fields = '__all__'

Django rest framework - NOT NULL constraint on a foreign Key

I have this Error :
IntegrityError at /api/post_flight_schedule/
NOT NULL constraint failed: flights_tailnumber.aircraft_type_id
When I try to add a new PosFlightSchedule object to DB over http://127.0.0.1:8000/api/pos_flight_schedule (Website/APIView)
I have the below serializer :
class PosFlightScheduleModelSerializer(ModelSerializer):
class Meta:
model = PosFlightSchedule
fields = ['pos_route_id', 'tail_number', 'pos_flight_number', 'pos_flight_departure_time', 'pos_flight_date',
'pax_count']
class PosFlightScheduleSerializer(serializers.Serializer):
pos_route_id = serializers.CharField(source='pos_route_id.route_id', read_only=False)
tail_number = serializers.CharField(source='tail_number.tail_number', read_only=False)
pos_flight_number = serializers.CharField(source='pos_flight_number.flight_number', read_only=False)
pos_flight_departure_time = serializers.CharField(source='pos_flight_departure_time.flight_departure_time', allow_null=True,
read_only=False)
pos_flight_date = serializers.CharField(source='pos_flight_date.flight_date', read_only=False)
pax_count = serializers.IntegerField(read_only=False)
def create(self, validated_data):
tail_number_data = validated_data.pop("tail_number")
tail_number = TailNumber.objects.create(**tail_number_data)
flight_number_data = validated_data.pop("pos_flight_number")
flight_number = FlightSchedule.objects.create(**flight_number_data)
flight_departure_time_data = validated_data.pop("pos_flight_departure_time")
print "DEP_TIME" + str(flight_departure_time_data)
flight_departure_time = FlightSchedule.objects.create(**flight_departure_time_data)
route_id_data = validated_data.pop("pos_route_id")
route_id = FlightScheduleDetail.objects.create(**route_id_data)
flight_date_data = validated_data.pop("pos_flight_date")
flight_date = FlightScheduleDetail.objects.create(**flight_date_data)
pax_count = validated_data.pop("pax_count")
schedule_obj = PosFlightSchedule.objects.create(**validated_data)
# if tail_number:
schedule_obj.set_tail_number(tail_number)
schedule_obj.set_pos_flight_number(flight_number)
schedule_obj.set_pos_flight_departure_time(flight_departure_time)
schedule_obj.set_pos_route_id(route_id)
schedule_obj.set_pos_flight_date(flight_date)
schedule_obj.set_pax_count(pax_count)
schedule_obj.save()
return schedule_obj
def update(self, instance, validated_data):
tail_number = validated_data.pop("tail_number")
flight_number = validated_data.pop("pos_flight_number")
flight_departure_time = validated_data.pop("pos_flight_departure_time")
route_id = validated_data.pop("pos_route_id")
flight_date = validated_data.pop("pos_flight_date")
pax_count = validated_data.pop("pax_count")
instance.__dict__.update(validated_data)
if tail_number:
instance.set_tail_number(tail_number)
if flight_number:
instance.set_pos_flight_number(flight_number)
if flight_departure_time:
instance.set_pos_flight_departure_time(flight_departure_time)
if route_id:
instance.set_pos_route_id(route_id)
if flight_date:
instance.set_pos_flight_date(flight_date)
if pax_count:
instance.set_pax_count(pax_count)
instance.save()
return instance
The model of the field which is giving error looks like :
class TailNumber(models.Model):
tail_number_id = models.AutoField(null=False, primary_key=True)
tail_number = models.CharField(max_length=20, null=False, blank=False, unique=True)
aircraft_type = models.ForeignKey(AircraftType, null=False, blank=False)
def __unicode__(self):
return u'%s' % self.tail_number
class Meta:
verbose_name_plural = "Tail Numbers"
I am not understanding what is going wrong here.
The error you get is probably due to the fact that the dictionary tail_number_data does not contain the keyword aircraft_type, which is expected by TailNumber.objects to create the row in the db, since you defined it with no possibility to be null
aircraft_type = models.ForeignKey(AircraftType, null=False, blank=False)
^^^^^
Check that the key "aircraft_type" does exist in the dictionary tail_number_data, or allow for it to be null. Furthermore, if you consider the latter option and that this information is supposed to come from a UI, you may also want to allow for aircraft_type to be blank. See differentiate null=True, blank=True in django for details.

Django forms not saving to DB

I'm writing an app that has an HTML page which must be capable of saving data into 2 models. I've created two separate forms and referenced them in the view, however the information is not saving into the DB.
Here are the views.py
def nuevoingreso(request):
if request.method == "POST":
formingreso = NuevoIngreso(request.POST)
formprodingreso = NuevoProdIngreso(request.POST)
if formingreso.is_valid():
ingreso = formingreso.save(commit=False)
ingreso.idUser = request.user
ingreso.Condominio = get_object_or_404(Condominios, idCondominio=request.session["idCondominio"])
ingreso.save()
ingresoprod = formprodingreso.save()
for i in range(5):
if ProductosIngresos.SubtotalP != "" and ProductosIngresos.IvaP != "" and ProductosIngresos.TotalP != "":
ingresoprod.ProductosIngresos(Concepto=request.POST.get("Concepto"+str(i), ""), SubtotalP=request.POST.get("SubtotalP"+str(i), ""), IvaP=request.POST.get("IvaP"+str(i), ""), TotalP=request.POST.get("TotalP"+str(i), ""))
ingresoprod.save()
return HttpResponseRedirect("/propiedades/")
else:
return render(request, "immovelc/nuevoingreso.html",
{"formingreso": formingreso, "formprodingreso": formprodingreso})
propiedadesing = PropiedadesCond.objects.all()
context = ({"propiedadesing": propiedadesing})
return render(request, "immovelc/nuevoingreso.html", context)
forms.py
class NuevoIngreso(ModelForm):
class Meta:
model = Ingresos
fields = ["Numero", "Persona", "Fecha", "Observaciones", "Cobrado", "Subtotal", "Iva", "Total"]
def clean(self):
Numero = self.cleaned_data["Numero"]
Persona = self.cleaned_data["Persona"]
Fecha = self.cleaned_data["Fecha"]
if not Numero:
raise forms.ValidationError("El campo de numero es obligatorio")
if not Persona:
raise forms.ValidationError("El campo de cliente es obligatorio")
if not Fecha:
raise forms.ValidationError("El campo de fecha es obligatorio")
class NuevoProdIngreso(ModelForm):
class Meta:
model = ProductosIngresos
fields = ["Concepto", "SubtotalP", "IvaP", "TotalP"]
models.py
class Ingresos(models.Model):
idIngreso = models.AutoField(primary_key=True, null=False, max_length=15)
idCondominio = models.ForeignKey(Condominios)
idUser = models.ForeignKey(User)
Numero = models.CharField(max_length=100)
Persona = models.CharField(max_length=250, default="Ninguno")
Cobrado = models.CharField(max_length=100, default=0)
Observaciones = models.TextField(default="Ninguna")
Fecha = models.DateField()
Subtotal = models.CharField(max_length=100)
Iva = models.CharField(max_length=100)
Total = models.CharField(max_length=100)
def __unicode__(self):
return unicode(self.idIngreso)
class ProductosIngresos(models.Model):
idProductoIngreso = models.AutoField(primary_key=True, null=False, max_length=15)
idIngreso = models.ForeignKey(Ingresos)
Concepto = models.CharField(max_length=500)
SubtotalP = models.CharField(max_length=100)
IvaP = models.CharField(max_length=100)
TotalP = models.CharField(max_length=100)
def __unicode__(self):
return unicode(self.idProductoIngreso)
Thanks!
No offence, but this code is far from being correct.
Besides you've got many errors that you might want to remove.
Errors:
formprodingreso.is_valid() is never called
inside for i in range(5) you use a class as if it was an instance (ProductosIngresos.SubtotalP)
clean method in form has to be outside the Meta block
I believe what you want inside the loop is:
producto_ingreso = ProductosIngresos()
producto_ingreso.idIngreso = ingreso # better change to producto_ingreso.ingreso
producto_ingreso.Concepto=request.POST.get("Concepto"+str(i), "") # producto_ingreso.concepto
producto_ingreso.SubtotalP=request.POST.get("SubtotalP"+str(i), "") # producto_ingreso.subtotal_p
producto_ingreso.IvaP=request.POST.get("IvaP"+str(i), "")
producto_ingreso.TotalP=request.POST.get("TotalP"+str(i), ""))
producto_ingreso.save()
To make it cleaner, you can make this king of logic overridding the save() method of ModelForm. Or use inline formsets.
Confusion:
Model FKs are objects in Django, not integers. Better name them like condominio instead of idCondominio
Decimal columns (subtotal, iva, total) should be declared as deciaml i.e. models.DecimalField(max_digits=10, decimal_places=2)
clean method is intended for cross field validation (more than one field). Only one field should be validated by clean_numero f.e.
Over complication:
models have ID/PK by default, no need to explicit them (referenced as self.id or self.pk)
model unicode function is not giving any info
clean and ValidationError are superflous: modelform checks if attributes are requiered automatically
Convention errors:
attributes are always written_in_lowercase (SubtotalP -> subtotal_p)
I would seriously try to fix all of those if you dont want the developers maintaining your code hate you and make some voodoo on you.

Cannot assign "5809L": "PedidoComissao.artista" must be a "Cliente" instance

I have a model like below:
class PedidoComissao(models.Model):
artista = models.ForeignKey(Cliente, verbose_name='Artista')
pedido = models.ForeignKey(Pedido)
pedidoitem = models.ForeignKey(PedidoItem, verbose_name='Arte')
valor_receber = models.DecimalField(max_digits=11, decimal_places=2)
data_pagamento = models.DateTimeField(auto_now_add=False)
status = models.BooleanField(default=False)
origem_venda = models.CharField(null=True, blank=True, max_length=30)
class Meta:
verbose_name, verbose_name_plural = u'Comissão', u'Comissões'
When I try to insert data with a code like below:
comissao = PedidoComissao(artista = produto.artista_id,
pedido = pedido,
pedidoitem = item,
valor_receber = valor_receber,
origem_venda = origem_venda)
comissao.save()
I get an error like this:
Cannot assign "5809L": "PedidoComissao.artista" must be a "Cliente" instance.
What am I supposed to do?
artista = produto.artista_id
should probably be
artista = Cliente.objects.get(produto.artista_id)
but its hard to tell exactly,since we dont know what produto is
the problem is your model expects an actual Cliente instance not just its id ...
You are doing PedidoComissao(artista=produto.artista_id, ...), but artista should be an instance of the model class, not the id. You can either do PedidoComissao(artista_id=produto.artista_id, ...) or PedidoComissao(artista=produto.artista, ...)

Categories