Django Filtering between dates - django

I am creating a filter in heatmap where the filter will only extract the date from and to date transaction only. I am not sure with the codes on the filter date but I have not received an error, It only goes top of the page. My HTML for date is MM/DD/YYYY. I am not sure if it helps. But how can I embed filter between dates? Thank you
Views
def index_map(request):
if request.method == "POST":
fromdate = request.POST.get('fromdate')
todate = request.POST.get('todate')
df = pd.DataFrame(IncidentGeneral.objects.filter(user_report__date__date__range=(fromdate, todate)).values('user_report__latitude', 'user_report__longitude', 'accident_factor'))
print(df)
# coordenadas = list(IncidentGeneral.objects.values_list('user_report__latitude','user_report__longitude'))[-1]
map1 = folium.Map(location=[14.676208, 121.043861],
zoom_start=12,
)
# df = df.dropna(axis=0, subset=['user_report__latitude', 'user_report__longitude', 'accident_factor', 'user_report__date'])
# mapquestopen
fg3=folium.FeatureGroup(name='Map with Markers', show=True)
map1.add_child(fg3)
# marker_cluster = MarkerCluster().add_to(fg)
folium.TileLayer(('openstreetmap'), attr='openstreetmap').add_to(map1)
# folium.TileLayer('mapquestopen', attr='mapquestopen').add_to(map1)
# folium.TileLayer('MapQuest Open Aerial', attr='MapQuest Open Aerial').add_to(map1)
folium.TileLayer('cartodbpositron', attr='cartodbpositron').add_to(map1)
folium.TileLayer('cartodbdark_matter', attr='cartodbdark_matter').add_to(map1)
plugins.Fullscreen(position='topright').add_to(map1)
folium.LayerControl().add_to(map1)
for id,row in df.iterrows():
folium.Marker(location=[row['user_report__latitude'],row['user_report__longitude']], icon=folium.Icon(icon="car", prefix='fa') ,popup=row['accident_factor']).add_to(fg3)
# folium.Marker(coordenadas).add_to(map1)
# df['user_report__date'] = df['user_report__date'].sort_values(ascending=True)
# data = []
# for _, d in df.groupby('user_report__date'):
# data.append([[row['user_report__latitude'], row['user_report__longitude'], row['accident_factor']] for _, row in d.iterrows()])
map1 = map1._repr_html_()
context = {
'map1': map1
}
return render(request, 'index1.html', context)
Views
class UserReport(models.Model):
PENDING = 1
APPROVED = 2
REJECTED = 3
STATUS = (
(PENDING, 'Pending'),
(APPROVED, 'Approved'),
(REJECTED, 'Rejected')
)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
description = models.TextField(max_length=250, blank=True)
address = models.CharField(max_length=250)
country = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=50, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
pin_code = models.CharField(max_length=6, blank=True, null=True)
latitude = models.FloatField(max_length=20, blank=True, null=True)
longitude = models.FloatField(max_length=20, blank=True, null=True)
upload_photovideo = models.FileField(upload_to='incident_report/image', blank=True, null=True)
date = models.DateField(auto_now_add=False, auto_now=False, blank=True, null=True)
time = models.TimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
status = models.PositiveSmallIntegerField(choices=STATUS, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def get_status(self):
if self.status == 1:
incident_status = 'Pending'
elif self.status == 2:
incident_status = 'Approved'
elif self.status == 3:
incident_status = 'Rejected'
return incident_status
def save(self, *args, **kwargs):
super(UserReport, self).save(*args, **kwargs)
if self.upload_photovideo:
if ".jpg" in self.upload_photovideo.url or ".png" in self.upload_photovideo.url:
#check if image exists before resize
img = Image.open(self.upload_photovideo.path)
if img.height > 1080 or img.width > 1920:
new_height = 720
new_width = int(new_height / img.height * img.width)
img = img.resize((new_width, new_height))
img.save(self.upload_photovideo.path)
HTML
<div class="row">
<!-- Heat Map-->
<div class="col-xl-12">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div
class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Heat Map</h6>
</div>
<!-- Card Body -->
<div class="card-body">
<div>
<div class="container">
<div class="row mt-4">
<div class="col-md-10 offset-md-1">
<form method="post">
{% csrf_token %}
<div class="modal-header">
<h4 class="modal-title">Filter Reports</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>From</label>
<input type="date" name="fromdate" class="form-control date" required>
</div>
<div class="form-group">
<label>Until</label>
<input type="date" name="todate" class="form-control date" required>
</div>
<label class="text-danger">Please ensure that the correct dates has been selected.</label>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel">
<input type="submit" class="save-myreports-btn" value="Save Changes">
</div>
</form>
{{ map1|safe }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- End of Heat Map-->
</div>

I'm guessing what you mean is you want to filter your objects based on the to and from dates.
In that one way is to use the range lookup like you do but the issue is you're using the field date from the user report instead of created_at which you have in your UserReport model.
def index_map(request):
if request.method == "POST":
fromdate = request.POST.get('fromdate')
todate = request.POST.get('todate')
df = pd.DataFrame(IncidentGeneral.objects.filter(user_report__created_at__date__range=(fromdate, todate)).values('user_report__latitude', 'user_report__longitude', 'accident_factor'))
print(df)
# coordenadas = list(IncidentGeneral.objects.values_list('user_report__latitude','user_report__longitude'))[-1]
map1 = folium.Map(location=[14.676208, 121.043861],
zoom_start=12,
)
# df = df.dropna(axis=0, subset=['user_report__latitude', 'user_report__longitude', 'accident_factor', 'user_report__date'])
# mapquestopen
fg3=folium.FeatureGroup(name='Map with Markers', show=True)
map1.add_child(fg3)
You can also do:
df = pd.DataFrame(IncidentGeneral.objects.filter(user_report__created_at__date__gte=fromdate, user_report__created_at__date__lte=todate).values('user_report__latitude', 'user_report__longitude', 'accident_factor'))

Related

How do I get rid of "Select a valid choice. That choice is not one of the available choices." error when using a ModelChoiceField?

I am trying to manually render options for a select filed in a django template. When I submit the form I get an error: "Select a valid choice. That choice is not one of the available choices." The error message also asks for required fields which I have provided.
locations models.py
class Location(models.Model):
name = models.CharField(max_length=20)
is_source = models.BooleanField(default=False)
is_destination = models.BooleanField(default=False)
def __str__(self):
return self.name
orders models.py
class Order(models.Model):
order_number = models.IntegerField(unique=True)
order_date = models.DateField(auto_now_add=True)
type = models.CharField(max_length=15, choices=TYPES)
source = models.ForeignKey(Location, default=1, on_delete=models.SET_DEFAULT, related_name='ordered_here')
destination = models.ForeignKey(Location, default=1, on_delete=models.SET_DEFAULT, related_name='delivered_here')
items = models.TextField()
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name='orders_to_serve')
customer = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name='orders_made')
status = models.CharField(max_length=15, choices=STATUSES)
orders forms.py
class OrderForm(ModelForm):
source = forms.ModelChoiceField(queryset=Location.objects.filter(is_source=True))
destination = forms.ModelChoiceField(queryset=Location.objects.filter(is_destination=True))
class Meta:
model = Order
fields = ['source', 'destination', 'items']
def save(self, commit=True):
instance = super().save(commit=False)
instance.order_number = math.floor(time.time())
instance.type = 'Purchase'
instance.customer = self.context.get('request').user
instance.status = 'New'
if commit:
instance.save()
return instance
orders create.html
<form class="" method="POST">
{% csrf_token %}
<h1 class='text-center'>Make an order</h1>
<div class='row'>
<div class='col-md-6 px-2'>
<span class="fw-bold mx-2">Buy from</span>
<div class="control-container border-primary d-flex align-items-center">
<i class="fa fa-map"></i>
<select class="control ms-1 flex-grow-1" type="text" name="{{form.source.html_name}}" required >
{% for value,label in form.source.field.choices %}
<option value="{{value}}">{{label}}</option>
{% endfor %}
</select>
</div>
</div>
<div class='col-md-6 px-2'>
<span class="fw-bold mx-2">Receive in</span>
<div class="control-container border-primary d-flex align-items-center">
<i class="fa fa-map"></i>
<select class="control ms-1 flex-grow-1" type="text" name="{{form.destination.html_name}}" required >
{% for value,label in form.destination.field.choices %}
<option value="{{value}}">{{label}}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class='row'>
<div class='col-12 px-2'>
<span class="fw-bold mx-2">List items (e.g. 2 X Luxaire Double Bed matress)</span>
<div class="control-container border-primary d-flex align-items-center">
<textarea class="control ms-1 flex-grow-1" rows="10" name="{{form.items.html_name}}" placeholder='e.g. 2 X Luxaire Double Bed matress' required></textarea>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary w-100 ">Order</button>
</form>
orders view.py
class OrderUpdateView(generic.edit.UpdateView):
model = Order
template_name = 'orders/update.html'
context_object_name = 'order'
form_class = OrderForm
I have eventually solved the problem by making the customer field in the order model nullable. I also had given my textarea in the order create template a wrong field name. All is well now.
you cannot do this even if you managed to make the form ignore this error the model will raise the same error elso because you just tell him to select a value from given values ... if you wanna make it dynammic then make it as noraml CharFied()

ModelChoiceField fields are not saved, what should I do?

The site has the ability to create a post for a specific game. When you try to create a post, it is created but the ManyToManyField remain empty. How to fix it?
forms.py
class AddPost(forms.ModelForm):
title = forms.CharField(label='Title', widget=forms.TextInput(attrs={'placeholder': 'Заголовок...'}),
help_text='Максимум 100 символів.')
games = forms.ModelChoiceField(queryset=Game.objects.filter(draft=False), widget=forms.Select, required=True)
tags = forms.ModelMultipleChoiceField(queryset=Tags.objects.all(), widget=forms.SelectMultiple(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
foreword_description = forms.CharField(label='Small Description',
widget=forms.Textarea(attrs={'placeholder': 'Коротке описання...'}),
help_text='Максимум 335 символів.')
description = forms.CharField(label='Description', widget=CKEditorUploadingWidget())
rank = forms.FloatField(label='Rank', widget=forms.TextInput(attrs={'placeholder': 'Оцінка...'}))
good = forms.ModelChoiceField(queryset=Good.objects.all(), widget=forms.Select(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
bad = forms.ModelChoiceField(queryset=Bad.objects.all(), widget=forms.Select(
attrs={'style': "padding: 10px; background:#edf2ff; border:none;"}))
url = forms.SlugField(label='Title', widget=forms.TextInput(attrs={'placeholder': 'Унікальний ідентифікатор...'}),
help_text='Максимум 255 символів.')
premiere = forms.DateField(label='Date', widget=forms.SelectDateWidget(attrs=({'style': 'width: 10%; display: inline-block;'})),
help_text='У форматі: 24.03.2022.')
class Meta:
model = Post
fields = (
'title', 'games', 'tags', "foreword_description", "description", "rank", "good", "bad", "url", "premiere",)
views.py
def addpost(request):
if request.method == "POST":
form = AddPost(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('../blogs/')
else:
form = AddPost()
data = {
'form': form,
'add': True
}
return render(request, 'gamelibs/user-post-manager.html', {'form': form})
models.py
class Game(models.Model):
title = models.CharField("Назва", max_length=100)
tagline = models.CharField("Слоган", max_length=500, default='')
description = models.TextField("Описання")
description_small = models.CharField("Описання коротко", max_length=100, null=True)
poster = models.ImageField("Постер", upload_to="games/poster/")
banner = models.ImageField("Банер", upload_to="games/banner/", null=True)
treiler = models.CharField("Трейлер", max_length=500, null=True)
treiler_img = models.ImageField("Інтро терейлеру", upload_to="games/intro/", null=True)
country = models.CharField("Країна", max_length=30)
company = models.ManyToManyField(Company, verbose_name="Компанія", related_name="company_game")
ganres = models.ManyToManyField(Ganre, verbose_name="Жанри")
price = models.FloatField("Ціна", help_text="У форматі 10.00", max_length=100)
sale_price = models.IntegerField('Скидка в процентах', blank=True, default=0)
world_premiere = models.DateField("Дата виходу", default=date.today)
budget = models.PositiveIntegerField("Бюджет", default=0, help_text="вказуйте сумму в доларах.")
category = models.ManyToManyField(Category, verbose_name="Категорія")
url = models.SlugField(max_length=255, unique=True)
os = models.CharField("Операційні системи", max_length=100)
processor = models.CharField("Процесор", max_length=100)
memory = models.CharField("Операційна памьять", max_length=100)
graphics = models.CharField("Відеокарта", max_length=100)
hard_drive = models.CharField("Місце на диску", max_length=100)
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',
related_query_name='hit_count_generic_relation', default=0)
draft = models.BooleanField("Чернетка", default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("game_details", kwargs={"slug": self.url})
def get_sale(self):
if self.sale_price == 100:
return 'FREE'
elif self.sale_price == 0:
return f'{self.price}'
else:
price = float(self.price * (100 - self.sale_price) / 100)
x = float('{:.2f}'.format(price))
return x
class Meta:
verbose_name = "Гра"
verbose_name_plural = "Ігри"
class Tags(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("tag_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Тег"
verbose_name_plural = "Теги"
class Good(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("good_blog_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Позитив"
verbose_name_plural = "Позитивні"
class Bad(models.Model):
title = models.CharField("Заголовок", max_length=100)
url = models.SlugField(max_length=160, unique=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("bad_blog_filter", kwargs={"slug": self.url})
class Meta:
verbose_name = "Негатив"
verbose_name_plural = "Негативні"
class Post(models.Model):
title = models.CharField("Заголовок", max_length=100)
games = models.ManyToManyField(Game, verbose_name="Вкажіть гру", help_text="Вказати тільки одну гру!",
related_name='games')
tags = models.ManyToManyField(Tags, verbose_name="Теги", help_text="Вказати тільки 4 тега!")
foreword_description = models.TextField("Передмова", max_length=335)
description = models.TextField("Описання")
rank = models.FloatField("Оцінка", default=0, help_text="Від 1 до 10")
good = models.ManyToManyField(Good, verbose_name="Позитивні речі", help_text="Максимальна кількість 4")
bad = models.ManyToManyField(Bad, verbose_name="Негативні речі", help_text="Максимальна кількість 4")
premiere = models.DateField("Дата публікації", default=date.today)
url = models.SlugField(max_length=255, unique=True, default="Введіть унікальний аудентифікатор")
hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk',
related_query_name='hit_count_generic_relation')
draft = models.BooleanField("Чернетка", default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post_details", kwargs={"slug": self.url})
class Meta:
verbose_name = "Пост"
verbose_name_plural = "Пости"
html
<form method="POST" enctype="multipart/form-data" name="filter-form">{% csrf_token %}
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Заголовок:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.title }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.title.help_text }}</i></h6>
{{ form.title.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Оберіть гру:</label>
<div class="col-sm-10">
<div class=" col-sm-10
field-games">
<div class="related-widget-wrapper">
{{ form.games }}
{{ form.games.errors }}
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Оберіть теги:</label>
<div class="col-sm-10">
{{ form.tags }}
{{ form.tags.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Коротке описання:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.foreword_description }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.foreword_description.help_text }}</i></h6>
{{ form.foreword_description.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Описання:</label>
<div class="col-sm-10">
{{ form.description }}
{{ form.description.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Оцінка гри:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.rank }}
</div>
{{ form.rank.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Позитивні речі:</label>
<div class="col-sm-10">
{{ form.good }}
{{ form.good.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="new_password">Негативні речі:</label>
<div class="col-sm-10">
{{ form.bad }}
{{ form.bad.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">URL:</label>
<div class="col-sm-10">
<div class="youplay-input">
{{ form.url }}
</div>
<h6><i class="fa fa-circle-exclamation"> {{ form.url.help_text }}</i></h6>
{{ form.url.errors }}
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="cur_password">Дата:</label>
<div class="col-sm-10">
{{ form.premiere }}
<h6><i class="fa fa-circle-exclamation"> {{ form.premiere.help_text }}</i></h6>
{{ form.premiere.errors }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Створити Пост</button>
</div>
</div>
</form>
What am I doing wrong or how else can I implement this? I just don't fully understand why the form is saved, but the ModelChoiceField fields are empty, why? I will be grateful for your answers
There is a disconnect between your many-to-many fields and your form.
Let's take 'game'. In your model it's a many-to-many field. But in your form it's a ModelChoiceField. A ModelChoiceField should link to a field that has a Foreignkey relationship (many to one), not a many to many. So, in this case, your model is saying a post can be about many different games, but your form only allowing the user to select one. With a one to many, you can still have many posts (plural) referring to the same game, but each individual post can only refer to one.
If you want the user to be able to select multiple games for each post, then the form should have a ModelMultipleChoiceField. If you only want a post to be about one game, then the model should have a ForiegnKey (one-to-many) rather than a many-to-many relationship. Then the form and the model will align and handle each other appropriately.

DeleteView in Django

I have this view that allows me to delete data. But the I keep getting the this error below whenever I click on the delete button. what I want to archive is when a user clicks the on GUARDAR, that model data should be deleted. But I keep getting the NoReverseMatch error bellow
raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'book_delete' with arguments '('',)' not found. 1 pattern(s) tried: ['(?P<pk>[0-9]+)/delete/$']
View.py
def book_delete(request, pk):
envío = get_object_or_404(Control, pk=pk)
data = dict()
if request.method == 'POST':
envío.delete()
data['form_is_valid'] = True
envíos = Control.objects.all().order_by('-fecha')
data['html_book_list'] = render_to_string('includes/partial_envio_list.html', {
'envíos': envíos
})
else:
context = {'envío': envío}
data['html_form'] = render_to_string('includes/partial_envío_delete.html', context, request=request)
return JsonReson
Model.py
class Control(models.Model):
control_id = models.AutoField(primary_key=True)
cliente = models.ForeignKey(Cliente, null=True, blank=True, on_delete=models.CASCADE)
familia = models.ForeignKey(Familia, null=True, blank=True, on_delete=models.CASCADE)
estado = models.ForeignKey(Estado, null=True, blank=True, on_delete=models.CASCADE)
fecha = models.DateField(blank=True, null=True)
Fecha_desde = models.DateField(blank=True, null=True)
Fecha_hasta = models.DateField(blank=True, null=True)
control_id_hash = models.CharField(max_length=260, db_collation='utf8_unicode_ci')
control_codigo = models.CharField(max_length=50, db_collation='utf8_unicode_ci')
URL
path('envío/<int:pk>/delete/', views.book_delete, name='book_delete'),
template
<form method="post" action="{% url 'agric:book_delete' control.pk %}" class="js-book-delete-form">
{% csrf_token %}
<div class="modal-body">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<div class="modal-status bg-danger"></div>
<div class="modal-body text-center py-4">
<h3>Are you sure?</h3>
<p class="lead">Do you really want to delete envío <strong>{{ control.control_codigo }}</strong>?</p>
</div>
<div class="modal-footer" style="background:#f4f5f7">
<button type="button" class="btn btn-default" data-bs-dismiss="modal">CANCELAR</button>
<button type="submit" class="btn modelbuttun btn-danger ">GUARDAR</button>
</div>
</div>
</fo

Foreign key model values return same value

I have looked at all answer and nothing quite helps me. I have a model Group
class Group(models.Model):
group_num = models.CharField(max_length=100)
group_name = models.CharField(max_length=200)
type = models.CharField(max_length=200)
def __str__(self):
return self.group_name
and a model Subgroup group
class Subgroup(models.Model):
sub_group_num = models.CharField(max_length=100)
sub_group_name = models.CharField(max_length=200)
group_number = models.ForeignKey(Group, on_delete=models.CASCADE,
related_name='group_numbers', verbose_name="Group Number")
group_in_name = models.ForeignKey(Group, on_delete=models.CASCADE,
related_name='group_names', verbose_name="Group Name")
def __str__(self):
return self.sub_group_name
when I reference the group_number and group_in_name from subgroup they give the same value in the template
The template is
<div class="col-md-2">
<label>Group Number</label>
</div>
<div class="col-md-10 form-group">
{{ form.group_number }}
</div>
<div class="col-md-2">
<label>Group Name</label>
</div>
<div class="col-md-10 form-group">
{{ form.group_in_name }}
</div>
<div class="col-sm-12 d-flex justify-content-end">
<button type="submit" class="btn btn-primary me-1 mb-1">Add Sub Group</button>
</div>
And view is
class AddSubGroupView(CreateView):
model = Subgroup
form_class = AddSubgroupForm
template_name = 'lookups/add_subgroup.html'
def form_valid(self, form):
return super().form_valid(form)

Using Dropdown values to set user ranks on creation

I have a user creation form in my Django web application. I am able to create a user normally.
I have a model in my application called user_type, which has the is_admin field, is_manager field and the user field linked to the User Foreign Key. I have added a dropdown in my user creation form to enable the Admin create a user and as well assign the user_type of the user using the dropdown.
I am now confused of how to grab the admin choice and enable the user_type depending on that.
models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
# CUSTOM USER FIELDS
firstname = models.CharField(max_length=30, blank=True, null=True)
lastname = models.CharField(max_length=30, blank=True, null=True)
telephone = models.IntegerField(blank=True, null=True)
address = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
updated_at = models.DateTimeField(auto_now=True, blank=True, null=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class user_type(models.Model):
is_admin = models.BooleanField(default=False)
is_manager = models.BooleanField(default=False)
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
if self.is_manager == True:
return User.get_email(self.user) + " - is_manager"
else:
return User.get_email(self.user) + " - is_admin"
views.py
def AddUser(request):
if request.method == "POST":
email = request.POST.get('email')
telephone = request.POST.get('telephone')
firstname = request.POST.get('firstname')
lastname = request.POST.get('lastname')
address = request.POST.get('address')
zipcode = request.POST.get('zipcode')
city = request.POST.get('city')
region = request.POST.get('region')
country = request.POST.get('country')
password = User.objects.make_random_password()
# is_manager = request.POST.get('is_manager')
try:
user = User.objects.create_user(email=email, telephone=telephone, firstname=firstname, password=password,
lastname=lastname, address=address, zipcode=zipcode, city=city, country=country)
user.send_welcome_mail(new_password)
# if is_manager == True:
# user.user_type.is_manager == True
# else:
# user.user_type.is_admin == True
user.save()
messages.success(request, "User Created Successfully!")
return redirect('users')
except Exception as e:
messages.error(request, "Failed to Create User!" + str(e))
return redirect('users')
return render(request, "core/adduser.html")
adduser.html
<form method="POST">
{% csrf_token %}
<div class="row">
<div class="col-md-6 col-sm-12">
<div class="form-group">
<input type="text" name="email" placeholder="Email Address" class="form-control">
</div>
</div>
<div class="col-md-6 col-sm-12">
<div class="form-group">
<input type="text" name="telephone" placeholder="Telephone" class="form-control">
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="form-group">
<input type="text" name="firstname" placeholder="Firstname" class="form-control">
</div>
</div>
<div class="col-md-4 col-sm-12">
<div class="form-group">
<input type="text" name="lastname" placeholder="Lastname" class="form-control">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<select class="custom-select2 form-control" name="user_type" style="width: 100%; height: 38px;">
<optgroup label="Select User Type">
<option value="M" name="is_manager">Manager</option>
<option value="A" name="is_admin">Admin</option>
</optgroup>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="form-group">
<textarea name="address" placeholder="Address" class="form-control"></textarea>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Create User</button>
</form>
Few changes to code style before explaining:
Rename user_type to UserType as it is suggested in Django Models.
Rename the view AddUser to add_user as it is suggested in PEP8 for function names.
In your add_user view:
if request.method == "POST":
# ...get your fields from the form
user_type = request.POST.get("user_type")
# ...create your user here
# assign default values first
is_admin = False
is_manager = False
# parse value from the form input
if user_type == "M":
is_manager = True
elif user_type == "A":
is_admin = True
# now create 1-to-1 field
user_type = UserType.objects.create(
user=user, is_admin=is_admin, is_manager=is_manager
)
Few more suggestions:
It is better to use user = User.objects.get(email=email) first to check if that user exists and handle that scenario. .get() function will give User.DoesNotExist exeption, handle that one for creating the user. Try to avoid generic Exception class as much as it is possible.
Use a Model Form for checking the input from the client, it will make sure that your inputs are good for the model requirements like required fields, field lengths and etc. before even trying to create that model.