how to add values to a ManyToManyField - django

I have the following model that has a field called who_can_see and I don't know how to add data to this filed nor the type of data (dictionary, array...)
#modles.py
class Author(models.Model):
name = models.CharField(max_length=200)
added_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=300)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
added_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
#🔴
who_can_see = models.ManyToManyField(
settings.AUTH_USER_MODEL, related_name='tweet_user', blank=True)
def __str__(self):
return self.title
you can see here where i add the 🔴, I am trying to who_can_see= [author, payload["who_can_see"]] so I expected the field who_can_see to be an array but when I make the POST request i got 500 error
#api_view(["POST"])
#csrf_exempt
#permission_classes([IsAuthenticated])
def add_book(request):
print({"request.data": request.data})
payload = request.data
user = request.user
try:
author = Author.objects.get(id=payload["author"])
book = Book.objects.create(
title=payload["title"],
description=payload["description"],
added_by=user,
author=author,
# who_can_see= [author, payload["who_can_see"]] # 🔴
)
serializer = BookSerializer(book)
return JsonResponse({'books': serializer.data}, safe=False, status=status.HTTP_201_CREATED)
except ObjectDoesNotExist as e:
return JsonResponse({'error': str(e)}, safe=False, status=status.HTTP_404_NOT_FOUND)
except Exception:
return JsonResponse({'error': 'Something terrible went wrong'}, safe=False, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

You should first create the book and then add the who_can_see property. Like the example on the documentation
You are almost good in your case. It would look like :
def add_book(request):
print({"request.data": request.data})
payload = request.data
user = request.user
try:
author = Author.objects.get(id=payload["author"])
book = Book.objects.create(
title=payload["title"],
description=payload["description"],
added_by=user,
author=author,
)
book.who_can_see.add(author)
serializer = BookSerializer(book)
return ...
EDIT : I realized that your model is not coherent with your view. Why do you link who_can_see to AUTH_USER_MODEL and not Author ? According to your view, your model should be :
who_can_see = models.ManyToManyField(Author,related_name='tweet_user', blank=True)

Related

Tell me how to transfer this code from Html to models

There is a code in html {{post.author.posts.count}} that counts the number of posts by the author.
I have such a question, how to transfer it to views.py
def post_detail(request, post_id):
post = get_object_or_404(Post, id=post_id)
context = {
'post': post,
}
return render(request, 'posts/post_detail.html', context)
class model
class Post(models.Model):
text = models.TextField(verbose_name='Текст')
pub_date = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата публикации'
)
group = models.ForeignKey(
Group,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='posts',
verbose_name='Группа',
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='posts',
verbose_name='Автор',
)
def __str__(self):
return self.text
I need to find an existing post, find its author and sort all posts by this author and calculate the total number of posts
You can not pass values form HTML to views in Django, but you can create #property to count all posts of the specific author.
you can try like this
models.py
class Post(models.Model):
text = models.TextField(verbose_name='Текст')
pub_date = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата публикации'
)
group = models.ForeignKey(
Group,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='posts',
verbose_name='Группа',
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='posts',
verbose_name='Автор',
)
def __str__(self):
return self.text
views.py
def Demoview(request,post_id):
get_post = Post.object.get(id=post_id)
author_of_post = get_post.author
all_post_of_author= Post.object.filter(author__id=get_blog.author.id)
count_all_post_of_author= Post.object.filter(author__id=get_blog.author.id).count()
context = {
'author_of_post':author_of_post,
'all_post_of_author':all_post_of_author,
'count_all_post_of_author':count_all_post_of_author,
}
return render(request,'post.html',context)
Happened. Here is the code that came out.
def post_detail(request, post_id):
post = get_object_or_404(Post, id=post_id)
author = post.author
post_count = Post.objects.filter(author=author).count()
context = {
'author': author,
'post_count': post_count,
'post': post,
}
return render(request, 'posts/post_detail.html', context)

Djnago Form getting Error while edit record

I am getting Issue while edit a record based on CHatquestion ID, if option is null then i need to add a record based on same chatquestion id, if chatqustion id exist in option it will work,
i am trying to multiple way to solve this issue but still can't find solution.
Models.py # thease are all 3 models
class Problem(models.Model):
Language = models.IntegerField(choices=Language_CHOICE, default=1)
type = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return self.type
class ChatQuestion(models.Model): # Eding record based on chatquestion id
question = RichTextField(null=True, blank=True)
problem_id = models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
)
def __str__(self):
return self.question
is_first_question = models.BooleanField(default=False)
class Option(models.Model):
option_type = models.CharField(max_length=250, null=True, blank=True)
question_id = models.ForeignKey(
ChatQuestion,
models.CASCADE,
verbose_name='Question',
null=True,
blank=True
)
problem=models.ForeignKey(
Problem,
models.CASCADE,
verbose_name='Problem',
null=True,
blank=True
)
next_question_id = models.ForeignKey(ChatQuestion, on_delete=models.CASCADE, null=True, blank=True,
related_name='next_question')
def __str__(self):
return self.option_type
forms.py
class EditQuestionForm(forms.ModelForm):
class Meta:
model = ChatQuestion
fields =('question','problem_id')
class EditOptionForm(forms.ModelForm):
class Meta:
model = Option
fields =('option_type',)
views.py
def question_edit(request,id=None):
if id is not None:
queryset = get_object_or_404(ChatQuestion,pk=id)
queryset1=get_object_or_404(Option,question_id=queryset )
else:
queryset = None
queryset1 = None
if request.method=="POST":
form = EditQuestionForm(request.POST ,instance=queryset)
form1=EditOptionForm(request.POST, instance=queryset1)
if form.is_valid() and form1.is_valid():
question=form.cleaned_data['question']
option_type=form1.cleaned_data['option_type']
if id:
queryset.question=question
queryset.save()
queryset1.option_type=option_type
queryset1.save()
messages.success(request,'Sucessful')
return redirect('/fleet/list_chatbot')
else:
print(form.errors)
messages.error(request,'Please correct following',form.errors)
elif id:
form = EditQuestionForm(instance=queryset)
form1=EditOptionForm(instance=queryset1)
if not queryset1:
form1=EditOptionForm()
else:
form = EditQuestionForm()
form1=EditOptionForm()
context={
'form':form,
'form1':form1
}
return render(request,'chatbot/question_edit.html',context=context)

Django saveing logged in logged in user as ForeignKey

I have model with a ForeignKey "log_written_by" and I want that to be the logged in user.
How should i state that in my forms.py as a hiddenfield?
class AssetLog(models.Model):
# Relationships
log_written_by = models.ForeignKey("auth.User", on_delete=models.SET_NULL, blank=True, null=True)
asset_case = models.ForeignKey("asset_app.AssetCase", on_delete=models.CASCADE)
# Fields
date_time_log = models.DateTimeField()
notes = models.TextField(max_length=1024)
created = models.DateTimeField(auto_now_add=True, editable=False)
class Meta:
pass
def __str__(self):
return str(self.pk)
def get_absolute_url(self):
return reverse("asset_app_AssetLog_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_AssetLog_update", args=(self.pk,))
You can do the following:
class AssetLogForm(forms.ModelForm):
class Meta:
model = AssetLog
fields = ('log_written_by ', '...,')
widgets = {'log_written_by ': forms.HiddenInput()}
See this related StackOverflow post here.

Python: How to solve the issue : 'badly formed hexadecimal UUID string' in Django

I have created 'post' model in which I included 'post_id' as the primary key field. When I am trying to create a post, it is raising an error: 'badly formed hexadecimal UUID string'. I would appreciate helping me in solve this.
Here's my code.
Models.py:
class Post(models.Model):
post_id = models.UUIDField(primary_key=True, default='uuid.uuid4', editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
objects = PostManager()
def __unicode__(self):
return self.post_id
def __str__(self):
return self.post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.post_id})
class Meta:
ordering = ["-timestamp", "-Time"]
views.py:
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
print(form.cleaned_data.get("post_id"))
instance.user = request.user
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
return render(request, "loggedin_load/post_load.html", context)
I would do something like this:
from django.utils.encoding import python_2_unicode_compatible
#python_2_unicode_compatible
class Post(models.Model):
# Instead of default, maybe do null=True to take old entries into account?
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
# You may want to reconsider the naming of the "To" field
# to avoid capital letters and built-in functions
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now_add=True)
objects = PostManager()
# You can remove this with the decorator above
# def __unicode__(self):
# return self.id
def __str__(self):
return self.id # acts as your post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.id})
class Meta:
ordering = ["-timestamp", "-Time"]
Whenever an object is created, it will automatically be assigned an id, which will populate your __unicode__, __str__, and get_absolute_url.
You need to import the module and not use quotes around 'uuid.uuid4'.
It should be somewhat like:
import uuid # The uuid module
class Post(models.Model):
post_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # using the function uuid4 on the module
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
from1 = models.CharField(max_length=20)
To = models.CharField(max_length=20)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
objects = PostManager()
def __unicode__(self):
return self.post_id
def __str__(self):
return self.post_id
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"post_id": self.post_id})
class Meta:
ordering = ["-timestamp", "-Time"]
N.B I've not tested the above code, and I agree with some of the comments you shouldn't need a UUID for the post_id. Without knowing more I couldn't help further.

Django Rest Framework PUT request on unique model field

I have the following model
class Owner(models.Model):
user = models.OneToOneField(User, default=1, editable=True)
phone = models.CharField(max_length=40, null=True, blank=True)
address = models.CharField(max_length=255, null=True, blank=True)
city = models.CharField(max_length=255, null=True, blank=True)
state = USStateField(null=True, blank=True)
zip = models.CharField(max_length=20, null=True, blank=True)
def __str__(self):
return "%s %s" % (self.user.first_name, self.user.last_name)
class Device(CreationModificationMixin):
_STATUSES = (
('A', 'Active'),
('I', 'Inactive'),
('F', 'Failure'),
)
_TYPES = (
('S', 'Spa'),
('P', 'Pool'),
)
udid = models.CharField(max_length=255, verbose_name="Unique ID / MAC Address", null=False, blank=False, unique=True)
type = models.CharField(max_length=1, choices=_TYPES, null=False, blank=False)
title = models.CharField(max_length=255, null=False, blank=False)
status = models.CharField(max_length=1, default='A', choices=_STATUSES)
pinged = models.DateTimeField(null=True)
owner = models.ForeignKey(Owner, verbose_name="Owner", null=True, blank=True)
def __str__(self):
return self.udid
I have the following serializer
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = ('id', 'udid', 'title', 'type', 'status', 'pinged', 'created')
I have the following API View defined:
class DeviceAPIView(APIView):
permission_classes = (IsAuthenticated,) # explicit
code_404 = "Device doesn't exists"
def get(self, request, device_id):
try:
d = Device.objects.get(id=device_id, owner=request.user.owner)
except Device.DoesNotExist:
return Response({'error': self.code_404}, 404)
serializer = DeviceSerializer(d)
return Response(serializer.data)
def put(self, request, device_id):
serializer = DeviceSerializer(data=request.DATA)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
data = serializer.data
data['id'] = id
d = Device(**data).save()
serializer = DeviceSerializer(d)
return Response(serializer.data, status=status.HTTP_200_OK)
PUT request on existing device
{
"udid": "38-2C-4A-47-C2-ED",
"title": "Backyard pool",
"type": "S"
}
gives me back
{
"udid": ["This field must be unique."]
}
However I'm updating the record and passing the same UDID it has. So I'm not getting a duplicate in DB but DRF thinks the other way.
What I need to achieve is
If UDID of the same record is not changed - then no error should be raised
if UDID of the record changes and now it's the same as some of record's UDID then error should be returned.
As per the comments implementing the put method closer to the reference implementation in the docs should fix the issue.
def put(self, request, pk, format=None):
device = self.get_object(pk)
serializer = DeviceSerializer(device, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Saving instances has a bit more information on creating, updating and saving instances by using the serializer class methods.