Django: Delete or empty content of a row in UpdateView - django

I'm looking to delete or empty a specific row in my table/model in my UpdateView. I have a team and employees in the team. I have made an update view that when "yes" is pressed, the team becomes archived. I want to additionally delete or empty the employee's numbers when doing so. How would I approach that?
I know it might be weird, but the idea is that the employee's numbers should be destroyed once the team is archived, while the rest of the data still stands.
Team Model
class Team(models.Model):
slug = models.SlugField(max_length=200)
teamname = models.CharField(max_length=50, help_text="Indtast holdnavn.", null=False, primary_key=True)
is_active = models.BooleanField(default=True)
Employee Model
class Employee(models.Model):
id = models.AutoField(primary_key=True)
slug = models.SlugField(max_length=200)
emp_num = models.IntegerField(help_text="Indtast medarbejderens MA-nummer. (F.eks 123456)")
firstname = models.CharField(max_length=30, help_text="Indtast medarbejderens fornavn.")
lastname = models.CharField(max_length=30, help_text="Indtast medarbejderens efternavn.")
teamname = models.ForeignKey('Hold', on_delete=models.CASCADE, null=True)
UpdateView
My updateView is using team, as its that model I'm updating.
class ArchiveHoldView(UpdateView):
template_name = 'evalsys/medarbejder/archive_hold.html'
model = Team
form_class = ArchiveForm
def archive_view_team_with_pk(self, slug=None):
if slug:
team = Team.objects.get(slug=slug)
else:
team = self.team
args = {'team': team}
return render(self, 'evalsys/medarbejder/archive_hold.html', args)
def get_context_data(self, **kwargs):
context = super(ArchiveHoldView, self).get_context_data(**kwargs)
context['is_active'] = Team.objects.get(slug=self.kwargs.get('slug'))
return context
def get_success_url(self):
return reverse_lazy("evalsys:home")
Update View form
class ArchiveForm(forms.ModelForm):
def save(self, *args, **kwargs):
self.instance.is_active = False
return super(ArchiveForm, self).save(*args, **kwargs)
is_active = BooleanField(required=False, widget=forms.HiddenInput())
class Meta:
model = Team
fields = ['is_active', ]
labels = {'is_active': 'Is Active'}

Related

How to update two models using one django form

I am facing one issue with django forms
Here is my model :
class User(models.Model):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class UserProfile(AuditFields):
user = models.ForeignKey(User, on_delete=models.CASCADE)
designation = models.CharField(max_length=200, blank=True)
contact_number = models.CharField(max_length=20, blank=True)
team = models.CharField(max_length=200, blank=True)
manager = models.CharField(max_length=200, blank=True)
joining_date = models.DateField(default=datetime.now)
I need to create a form for editing profile details of the current user
This is my form. But it is a model Form so only getting the detauls from the User Profile table only
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ['user']
How can I get first_name , last_name from User table and save it
Just add the fields as a CharField in form, and use cleaned_data attribute to fetch the data and save it:
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=30,required=True)
last_name = forms.CharField(max_length=30,required=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance:
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
class Meta:
model = UserProfile
exclude = ['user']
def save(self, commit=False):
instance = super().save(commit=True)
user = instance.user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
return instance

How to update a field in the model using ForegnKey lookup?

I need to be able to update a field num_places in the Event model accessing it via event ForeignKey in the Participant model when the last is saved.
Here are my models.py:
class Event(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=500)
text = models.TextField()
image = models.ImageField(blank=True)
date = models.DateTimeField()
price = models.PositiveIntegerField()
num_places = models.PositiveIntegerField(default=50)
slug = models.SlugField()
class Participant(models.Model):
name = models.CharField(max_length=200)
participant_uuid = models.UUIDField(primary_key=False, verbose_name='UUID')
email = models.EmailField()
phone_regex = RegexValidator(regex=r'^\+7\d{10}$')
phone_number = models.CharField(validators=[phone_regex], max_length=12)
num_places = models.PositiveIntegerField(default=1)
event = models.ForeignKey(Event, on_delete=models.CASCADE)
paid = models.BooleanField(default=False)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
try:
self.full_clean(exclude=None)
self.event.num_places -= self.num_places # the value isn't updated
super().save(*args, **kwargs)
self.valid = True
self.non_field_errors = False
except ValidationError as e:
self.non_field_errors = e.message_dict[NON_FIELD_ERRORS]
self.valid = False
class Meta:
unique_together = ('name', 'email', 'phone_number', 'event')
The code with a comment has a problem: the num_places value in the Event model stays unchanged. How to fix it?
you need to save the modified object of Event.
self.event.save()
def save(self, *args, **kwargs):
try:
self.full_clean(exclude=None)
self.event.num_places -= self.num_places # the value isn't updated
self.event.save()
"""watch out this since you wanna do it at the end after setting valid, and non_fieild_errors"""
super().save(*args, **kwargs)
self.valid = True
self.non_field_errors = False
except ValidationError as e:
self.non_field_errors = e.message_dict[NON_FIELD_ERRORS]
self.valid = False

How to update data in django model to title case in views?

I'm trying to change a column of strings like 'HOSPITAL ZERO', "HOSPITAL ONE" from the database into title case or 'Hospital zero' in the views.py or models.py. I've tried both and can't get either to work for me.
Here is my code in views.py. Column is in Hospital Model under name, i.e. Hospital.name.
def results(request):
if request.method == "GET":
Q=()
out_words = request.GET.get('s')
context = RequestContext(request)
#here is where I tried to change it
qs = Price.objects.annotate(hospital__name=Lower('hospital__name'))
table = PriceTable(qs.filter(service__desc_us__icontains = out_words))
RequestConfig(request, paginate={'per_page': 10}).configure(table)
RequestConfig(request).configure(table)
else:
table = PriceTable(Price.objects.all())
RequestConfig(request).configure(table)
return render(request, 'results.html', {'table': table})
Here is how I tried in model.py.
class Hospital(models.Model):
"""Model representing Hospitals."""
hid = models.CharField(max_length = 8, null=True)
name = models.CharField(max_length=200, primary_key=True)
hopid = models.UUIDField(default=uuid.uuid4, help_text='Unique ID for this particular hospital in database')
address = models.CharField(max_length = 200, null = True)
class Meta:
ordering = ['hopid']
#here is where i tried to update it
def save(self, *args, **kwargs):
self.name = self.name.title()
return super(Hospital, self).save(*args, **kwargs)
def __str__(self):
"""String for representing the Model object."""
return f'{self.name} ({self.address})'
class Price(models.Model):
"""Model with all the hospital prices by service."""
priceid = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular service in database')
comments = models.CharField(max_length = 200, blank = True, null =True)
hospital = models.ForeignKey("Hospital", on_delete=models.SET_NULL, null=True)
class Meta:
ordering =['priceid']
def __str__(self):
return f'{self.hospital.name} (...)'
You can try this:
"HOSPITAL ONE".lower().capitalize()
my_string.lower().capitalize()
Here is an option:
def save(self, *args, **kwargs):
self.name = self.name.lower().capitalize()
return super(Hospital, self).save(*args, **kwargs)
Here's a new method for your Hospital model called get_title_case_name. Now you can access a hospital name by calling hospital_instance.get_title_case_name().
class Hospital(models.Model):
"""Model representing Hospitals."""
hid = models.CharField(max_length = 8, null=True)
name = models.CharField(max_length=200, primary_key=True)
hopid = models.UUIDField(default=uuid.uuid4, help_text='Unique ID for this particular hospital in database')
address = models.CharField(max_length = 200, null = True)
class Meta:
ordering = ['hopid']
def __str__(self):
"""String for representing the Model object."""
return f'{self.name} ({self.address})'
def get_title_case_name(self):
return self.name.capitalize()
Just add method to model:
def get_title_case_name(self):
return self.name.title()
In views/template you can run this method against model object.

How create trigger in Django Rest Framework to change booleanfield?

I have a question in django rest framework. Since I'm learning how to use some advanced options, I do not quite understand. I need to currently change a booleanfield every time a foreignkey is inserted into table.
How can I do this in model ?
Model:
class Persona(models.Model):
name = models.CharField(max_length=32)
cart = models.ForeignKey(Credit,null=True)
rg = models.IntergerField()
end = models.CharField(max_length=256)
details = models.TextField(blank=True, null=True)
order = models.ForeignKey(Order, null=True)
def __str__(self):
return self.cart
class Meta:
db_table='person'
app_label = 'bank'
class Credit(models.Model):
number = models.CharField(max_length=16, unique=True)
create_at = models.DateField(auto_add_now=True)
updated_at = models.DateField()
available = models.BooleanField()
def __str__(self):
return self.number
class Meta:
db_table = 'credit'
app_label = 'bank'
Serializer:
class PersonaSerializer(serializers.ModelSerializer):
order__id = serializers.ReadOnlyField(source='order.id')
class Meta:
model = Persona
fields = '__all__'
class Persona(viewsets.ModelViewSet):
allowed_methods = ('GET', 'POST', 'PUT', 'PATCH')
queryset = Persona.objects.all()
serializer_class = PersonaSerializer
You can override the create method on the ModelSerializer to achieve this:
def create(self, validated_data):
cart = validated_data['cart']
persona = super(PersonaSerializer, self).create(validated_data)
cart.available = True # update boolean
cart.save()
return persona
You can read more about this in the docs
If you want to handle this in your model you can override the Persona model save method:
class Persona(models.Model):
name = models.CharField(max_length=32)
cart = models.ForeignKey(Credit,null=True)
rg = models.IntergerField()
end = models.CharField(max_length=256)
details = models.TextField(blank=True, null=True)
order = models.ForeignKey(Order, null=True)
def __str__(self):
return self.cart
class Meta:
db_table='person'
app_label = 'bank'
def save(self, *args, **kwargs):
# Will only update the available field when the Persona
# instance is created and the cart field is not null
if not self.pk and self.cart:
self.cart.available = True
self.cart.save()
return super(Persona, self).save(*args, **kwargs)

Django CreateView filter foreign key in select field

I need some help with Django 2 and Python 3.
I'm using a CreateView to add new reccords in my database, but I need to make a filter for my Aviso form page to make the select field (field turma) to show only instances where the representante is the current user.
This is my model:
class Turma(models.Model):
nome = models.CharField(max_length=120, blank=False, null=False, help_text='Obrigatório.')
alunos = models.ManyToManyField(User, help_text='Obrigatório', related_name='alunos_matriculados')
data_cadastro = models.DateField(auto_now_add=True)
representante = models.ForeignKey(User, on_delete=models.PROTECT, blank=False, null=False)
colegio = models.ForeignKey(Colegio, on_delete=models.PROTECT, blank=False, null=False, help_text='Obrigatório.')
class Aviso(models.Model):
data_final = models.DateField(auto_now=False, auto_now_add=False, blank=False, null=False, verbose_name="Data Final")
comentarios = models.TextField(null=True, blank=True)
ultima_modificacao = models.DateField(auto_now=True)
data_post = models.DateField(auto_now_add=True)
turma = models.ForeignKey(Turma, on_delete=models.PROTECT, null=False, blank=False)
materia = models.ForeignKey(Materia, on_delete=models.PROTECT, null=False, blank=False)
This is my view:
class AvisoCreateView(LoginRequiredMixin, CreateView): #Cadastro de Aviso
template_name = 'form.html'
model = models.Aviso
login_url = '/login/'
success_url = reverse_lazy('visualizar_aviso')
fields = [
'turma',
'materia',
'tipo_aviso',
'comentarios',
'data_final'
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['titulo'] = 'Cadastrar aviso'
context['input'] = 'Adicionar'
return context
How could that be done?
You can add a queryset to the ForeignKey field.
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'].fields['turma'].queryset = Turma.objects.filter(representante=self.request.user)
context['titulo'] = 'Cadastrar aviso'
context['input'] = 'Adicionar'
return context
You could create a ModelForm for that model.
And based on this answer you could override the forms __init__() method to alter the fields queryset.
class AvisoForm(forms.ModelForm):
class Meta:
model = Aviso
fields = [
'data_final', 'comentarios', 'ultima_modificacao', 'data_post',
'turma', 'materia',
]
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
# restrict the queryset of 'Turma'
self.fields['turma'].queryset = self.fields['turma'].queryset.filter(
representante=user)
Then, in your view, replace the attribute fields with form_class:
class AvisoCreateView(LoginRequiredMixin, CreateView):
...
form_class = AvisoForm
...
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Maybe you need to adjust a few things for your specific case.
Let us know if that solved it.