I am now getting the file from my front-end and I set my model like this.
model.py
class User(models.Model):
name = models.CharField(max_length=50)
image= models.FileField(upload_to='image/', default=None)
intro= models.FileField(upload_to='info/', default=None)
view.py
class UserViewSet(viewsets.ModelViewSet):
serializer_class = LsRequestSerializer
queryset = User.objects.all()
http_method_names = ['post']
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
field = '__all__'
def create(self, validated_data):
newUser = User.objects.create(
name = validated_data['name']
image = validated_date['image']
intro = validated_date['intro']
)
return newUser
However, when I did the HTTP.POST in Postman, it gave the wrong path to save the image.
"http://localhost:8000/media/Koala.jpg"
But based on my design in the model with path_to, it should give:
"http://localhost:8000/media/image/Koala.jpg"
Update:
The strange thing is that when I tried to update a user by giving a new image using HTTP.Patch method, it then has the right path.
Update:
It turns out to be the problem that I cannot have multiple input filefield and upload_to different subfolders. How to solve this problem?
If I put the serializer as above, it can find the right path but it also means that these two fields are required. But in fact, these two fields are optional.
But if I put the if statement outside the create function, it cannot detect the correct path.
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
field = 'all'
def create(self, validated_data):
newUser = User.objects.create(
name = validated_data['name']
image = None
intro = None
)
if validate_data['image']:
newUser.image = validate_data['image']
if validate_data['intro']:
newUser.image = validate_data['intro']
return newUser
What's wrong with my code?
Well you should first check that if you specified the right path for media in your setting.py it should be something like this:
The place that you want to store those pictures:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
And as you want to see them like "http://localhost:8000/media/whatever/whatever.jpg" you should specified the MEDIA_URL like this:
MEDIA_URL = '/media/'
And then as you did it in your models the argument will be like:
upload_to='image/'
You can also read more about it here!
And as a side note if you want to deal with pictures then you can use ImageField rather than FileField.
Related
I'm trying to generate a unique filename for the uploaded file using the Django forms. I've tried uuid_upload_path app but that app doesn't work with the form. Below is my code
Forms.py
class HelpGuideForm(forms.ModelForm):
title = forms.CharField(max_length = 50)
image = forms.ImageField(required = False)
class Meta:
model = Helpguide
fields = ['title', 'image']
Models.py
from uuid_upload_path import upload_to
class HelpguideImage(models.Model):
image = models.ImageField(upload_to = upload_to, blank=True, null=True)
I want a unique name for all uploaded files. something like sd564sadasd61.jpg. I'm using Django 2.2
In your Model you can set the upload_to of the imagefield to a function and then generate the uuid.
A very simple (untested) example:
import uuid
Class MyModel(models.Model):
def get_path(instance, filename):
extension = filename.split('.')[-1]
uuid = uuid.uuid1().hex
return f'path/to/file/{uuid}.{extension}'
image = ImageField(upload_to=get_path)
What I understand of your problem, you can set initial for FORM class when initialising it. like:
help_guide_form = HelpGuideForm(initial={'headline': uuid.uuid4().hex}, instance= Helpguide)
from django docs. Also see the initial reference.
Using a custom ModelForm in my default (django admin) change view gives me an empty variable self.fields if the form gets rendered for a user with only view permissions (new in Django 2.1).
This is my code:
# models.py
class Door(ValidateOnSaveMixin, models.Model):
...
motor_type = models.ForeignKey(
MotorType,
on_delete=models.SET_NULL,
default=None,
blank=True,
null=True)
...
door_type = models.CharField(
max_length=3,
choices=DOOR_TYPES,
null=True,
default=None)
...
vehicle_variant = models.ForeignKey(
VehicleVariant,
on_delete=models.CASCADE)
class Meta:
unique_together = ("vehicle_variant", "location", "motor_type")
...
# admin.py
#admin.register(Door)
class DoorAdmin(ImportExportModelAdmin):
form = DoorAdminForm
list_display = ('descriptor', 'get_customer_link', 'get_variant', 'location', 'get_motor_type_link',
'window_type', 'door_type', 'drum_diameter', 'dist_per_motor_rotation')
fields = ('vehicle_variant', 'description', 'location', 'motor_type',
'drum_diameter', 'window_type', 'door_type')
...
# forms.py
class DoorAdminForm(ModelForm):
class Meta:
model = Door
fields = '__all__'
widgets = {
'motor_type': DoorMotorTypeWidget,
}
def __init__(self, *args, **kwargs):
super(DoorAdminForm, self).__init__(*args, **kwargs)
# this line is crashing on access with a user who has only the view permission, as self.fields is empty
self.fields['vehicle_variant'].queryset = VehicleVariant.objects.all().prefetch_related('customer').order_by('customer__name', 'name')
The root cause is related to the exclude attribute of the Meta class in DoorAdminForm.
No matter what i write to the fields/exclude attributes, always all of the model's fields get automatically put to the exclude list and prevent self.fields to be populated. And this makes my code crash.
Of course i can check for 'verhicle_variant' in self.fields but i don't understand the reason for that behaviour. I also couldn't find the part in the django source which populates the exclude attribute with all model fields.
Anybody has an idea if this is intended? Whats the root cause for that behaviour (ignoring the fields and exclude attribute of the Meta class)?
The point where all fields get put into exclude is here:
https://github.com/django/django/blob/cf79f92abee2ff5fd4fdcc1a124129a9773805b8/django/contrib/admin/options.py#L674
I have never used django admin with just 'view' permissions. Haven't really found a lot of information about how this should look like either: django-admin comes with add- and change-views amongst others, but no viewonly-view? Almost looks like it doesn't really know what to do with users that do not have 'change' permission. It directs them to the change_view and then notices that they are not allowed to change anything so it displays an empty form?
I suppose you could just declare all the fields as readonly for a viewonly-view?
UPDATE:
The field vehicle_variant won't be in form.fields as it would still be excluded due to not having change permission, but at least you don't crash on the form's init. I still have no idea what a change_view without change permissions should look like other than everything being readonly.
class DoorAdminForm(ModelForm):
qs = VehicleVariant.objects.prefetch_related('customer').order_by('customer__name', 'name')
model_field = Door._meta.get_field('vehicle_variant')
vehicle_variant = model_field.formfield(queryset=qs)
class Meta:
model = Door
fields = '__all__'
widgets = {
'motor_type': DoorMotorTypeWidget,
}
I'm trying to link 'owner' field of my model to an AbstractUser. I need it to be done automatically, the only think i'm able to do by myself is to allow user logged in to choice between every existing user with, what's not what i want. I would like to not have a field to manipulate, but a outcome serializer with id or username of User that added the model. I'm trying to find solutions for a few days, I've tried already combine ForeignKey, PrimaryKeys, OneToOneField, HiddenField, get_user, perform_create, but I'm for sure doing something wrong, and i'm almost lost with it. The last thing i tried is to def_perform in views like DRF QuickStart tutorial say, but without results.
I add some code sample to be more understandable:
There is my AbstractUser model:
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserProfile(AbstractUser):
username = models.CharField(max_length=20, unique=True)
...
i added it to AUTH_USER_MODEL = in the settings.
And there is other model which i want to link with User:
from django.db import models
from users.models.user import UserProfile
class MyPhoto(models.Model):
owner = models.ForeignKey(UserProfile, related_name='photos', on_delete=models.CASCADE, null=True)
image = models.ImageField(upload_to='Images')
serializer.py
class MyPhotoSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = MyPhoto
fields = ('pk', 'image', 'owner')
def create(self, validated_data):
photo = MyPhoto.objects.create(
image=validated_data['image']
)
photo.save()
return photo
views.py
class UpdateMyPhotoViewSet(viewsets.ModelViewSet):
queryset = MyPhoto.objects.all()
serializer_class = MyPhotoSerializer
permission_classes = (IsAuthenticated,)
def perform_create(self, serializer):
serializer.save(created_by=self.request.user)
and for now i can't see the owner field results.
Thanks in advance.
Let me explain what my problem is in more detail.
First I have a class 'UserInfo' which connected to User class of django.contrib.auth.models like below
models.py
class UserInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=15,blank=True,unique=True)
position = models.CharField(max_length=15,blank=True,unique=True)
class Meta:
default_permissions = ()
def __str__(self):
return self.position
then I wanted to use ModelForm because I can write less codes. The reason why I made CreateNewUser class is that I wanted to let user can see only [username, email, groups, user_permissions] and control those. (to prevent them to select superuser or staff or inactive options)
forms.py
class CreateNewUserInfo(forms.ModelForm):
class Meta:
model = UserInfo
fields = '__all__'
class CreateNewUser(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'groups', 'user_permissions']
problem happened in here. I wanted to use FormView to use generic view with class typed view so that I can write less codes(concise code). there is attribute named 'form_class' and I couldn't put two different class with it. I wanted to put different two class to one form with generic view.
views.py
class TestView(FormView):
form_class = CustomForm
template_name = 'manager/alltoall.html'
def form_valid(self, form):
At the end, I made new class in forms.py and wrote every field which I need like below.
forms.py
class CustomForm(forms.Form):
username = forms.CharField(initial='testname',max_length=150)
email = forms.EmailField()
phone_number = forms.CharField(max_length=15)
position = forms.CharField(max_length=15)
views.py
class TestView(FormView):
form_class = CustomForm
template_name = 'manager/alltoall.html'
def form_valid(self, form):
username = form.cleaned_data['username']
email = form.cleaned_data['email']
phone_number = form.cleaned_data['phone_number']
position = form.cleaned_data['position']
with transaction.atomic():
user = User.objects.create(username=username,email=email)
userinfo = UserInfo.objects.create(user=user,phone=phone_number,position=position)
userinfo.save()
user.save()
return super(TestView, self).form_valid(form)
Is there anyway to use ModelForm and FormView to show two different class in a form at the same time? Additionally, I used transaction like above because I wanted to save data in database with two different class. Is it right approach or Is there any other way to do that more conveniently(or efficiently) with built in functions in django?
Thank you for taking your time to read all. I wonder if it is too long, but I wanted to deliver what I wanted to know exactly. Thank you!
i need some help. I'm writting an app with django 1.6 and python 3.4.
My models:
class Account(models.Model):
number = models.IntegerField()
name = models.CharField(max_length = 100)
level = models.IntegerField()
parent_account = models.ForeignKey(Account, null=True, blank=True)
My View:
class InvoiceCreateView(CreateView):
model = Account
template_name = 'account/templates/create.html'
success_url = reverse_lazy('account_list')
Then when i create a new Account a dropdown list appear to select the Parent Account, everything fine, but i want to fill that dropdown list to accounts with level equal to 2 (example), not with all accounts.
something like this:
account.object.all().filter(level=2)
thanks for advance!
You can create your custom form and set the form_class variable in your view like:
class InvoiceCreateView(CreateView):
model = Account
form_class = AccountForm
template_name = 'account/templates/create.html'
success_url = reverse_lazy('account_list')
In your form, (I've named it AccountForm), you can define the parent field as desired:
class AccountForm(forms.ModelForm):
class Meta(object):
model = Account
parent = forms.ModelChoiceField(queryset=Account.objects.filter(level=2))
I guess this is what you are looking for:
account_list = account.objects.filter(level=2)
The Django Documentation on making queries also answers that question quite well.