I have the following code:
class CampaignModelTests(TestCase):
# https://docs.djangoproject.com/en/4.1/topics/testing/advanced/
def setUp(self):
# create some test campaigns
shop = Shop.objects.create(name='Test Shop')
self.factory = RequestFactory()
self.user = User.objects.create(shop_username='testuser', shop=shop)
self.merchant = User.objects.create(username='merchant', password='merchant123', is_merchant=True, shop=shop)
self.campaign = Campaign.objects.create(name='Test Campaign', shop=shop)
def test_campaign_creation(self):
request = self.factory.get(reverse('create-campaign'), {
'name': 'Test Campaign -1',
'shop': Shop(name='Test Shop').sid
})
request.user = self.merchant
print('request.user: ', request.user.is_merchant)
response = CampaignCreate.as_view()(request)
self.assertEqual(response.status_code, 200)
And I am getting the following error:
return request.user.is_merchant or request.user.is_superuser
AttributeError: 'AnonymousUser' object has no attribute 'is_merchant'
I have tried using self.client as well but still the same error.
self.client.force_login(self.merchant)
# send a request to the view
response = self.client.post(reverse('create-campaign'), {
'name': 'Test Campaign -1',
'shop': Shop(name='Test Shop').sid
})
self.assertEqual(response.status_code, 200)
Related
I want to create Aviz entry using AJAX form.
In the form the input material has a jquery ui function autocomplete, that gets all the material names from the Material Model.
When I submit the form I get this error in the console : ValueError: Cannot assign "'ADEZIV LIPIRE VATA MINERALA, CT 180, 25 KG CERESIT'": "Aviz.material" must be a "Material" instance.
I know that I need to get the input from the form, and turn it in a Material instance...but do not know how/did not find any info about this.
models.py:
class Material(models.Model):
name = models.CharField(max_length=255,default=None,verbose_name='Nume material')
class Aviz(models.Model):
material = models.ForeignKey(Material, on_delete=models.CASCADE,related_name="aviz")
quantity = models.FloatField(default=0,verbose_name="Cantitate")
views.py:
class AvizCreate(LoginRequiredMixin, AjaxCreateView):
model = Aviz
form_class = AvizForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['pk'] = self.kwargs.get('centrudecost')
return kwargs
#login_required
def autocomplete(request):
if 'term' in request.GET:
qs = Material.objects.filter(name__icontains=request.GET.get('term'))
name = list()
id = list()
cod_nexus = list()
name = [prod.name for prod in qs]
id = [prod.pk for prod in qs]
cod_nexus = [prod.cod_nexus for prod in qs]
return JsonResponse({"name": name, "id":id, "cod_nexus":cod_nexus}, safe=False)
templates.html
$('#id_material').autocomplete({
source: function(request, response) {
$.ajax({
url: "{% url 'materiale:autocomplete' %}",
dataType: "json",
data: {
term: request.term
},
success: function(data) {
response($.map(data.name, function(value, key) {
return {
label: data.name[key],
value: data.name[key],
id:data.id[key],
cod_nexus:data.cod_nexus[key]
}
}));
}
});
},
select: async function(event, ui) {
let resp = await fetch("{% url 'materiale:get_um' 1 %}".replace('1',ui.item.id));
let json = await resp.json()
$('#id_um').val(json);
}
})
}
forms.py:
class AvizForm(BootstrapHelperForm, forms.ModelForm):
material = forms.CharField()
um = forms.CharField()
class Meta:
model = Aviz
fields = ('centrudecost','data','aviz', 'material','um','quantity',)
widgets = {
'data': DateInput(),
'centrudecost': forms.HiddenInput(),
# 'material': forms.Select(attrs={'class': 'form-control'})
}
def __init__(self, *args, **kwargs):
pk = kwargs.pop('pk', None)
super(AvizForm, self).__init__(*args, **kwargs)
self.fields['um'].widget.attrs['readonly'] = True
I know that by deleting this material = forms.CharField() from the forms.py, the form works, and a Aviz instance is created referencing the material model, but i need to use the autocomplete function in the form
first time I ask on the website.
I was testing a Django Restframework app.
The is to check an unauthenticated user that wants to create a review.
I got this error:
TypeError: Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x7f5e95756920>.
this is the class test:
class ReviewTestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username="example", password="Password#123")
self.token = Token.objects.get(user__username=self.user)
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key)
self.stream = models.StreamPlatform.objects.create(
name="Netflix",
about="#1 Platform",
website="https://www.netflix.com"
)
self.watchlist = models.WatchList.objects.create(
platform=self.stream, title="Example Movie",
storyline="Example Movie",
active=True
)
self.watchlist2 = models.WatchList.objects.create(platform=self.stream, title="Example Movie",
storyline="Example Movie", active=True)
self.review = models.Review.objects.create(review_user=self.user, rating=5, description="Great Movie",
watchlist=self.watchlist2, active=True)
def test_review_create(self):
data = {
"review_user": self.user,
"rating": 5,
"description": "Great Movie!",
"watchlist": self.watchlist,
"active": True
}
response = self.client.post(
reverse('reviewcreate', args=(self.watchlist.id,)), data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(models.Review.objects.count(), 2)
response = self.client.post(
reverse('reviewcreate', args=(self.watchlist.id,)), data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
**#The test who cause the error**
def test_review_create_unauth(self):
data = {
"review_user": self.user,
"rating": 5,
"description": "Great Movie!",
"watchlist": self.watchlist,
"active": True
}
self.client.force_authenticate(user=None, token=None)
response = self.client.post(
reverse('reviewcreate', args=(self.watchlist.id,)), data)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
def test_review_update(self):
data = {
"review_user": self.user,
"rating": 4,
"description": "Great Movie! - Updated",
"watchlist": self.watchlist,
"active": False
}
response = self.client.put(
reverse('review-detail', args=(self.review.id,)), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_review_list(self):
response = self.client.get(
reverse('movie-review', args=(self.watchlist.id,)))
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_review_ind(self):
response = self.client.get(
reverse('review-detail', args=(self.review.id,)))
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_review_ind_delete(self):
response = self.client.delete(
reverse('review-detail', args=(self.review.id,)))
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
def test_review_user(self):
response = self.client.get(
'/watch/review/?username' + self.user.username)
self.assertEqual(response.status_code, status.HTTP_200_OK)
In data items, you are passing an object, and you have to pasa an id. Change this:
review_user: self.user.id
Thanks to everyone,
I found the mistake.
In fact the problem was not in the func in the tests.py but in the view,
where I misspelled:
permission_classes = [IsAuthenticated]
with:
permission_clasees = [IsAuthenticated]
So everything is fine now.
Thanks again to all of you
I got a JSON response from some url. I have to show that into rest api but i got error. Here is my code
views
class StoreView(APIView):
serializer_class = PostcodeLookupSerializer
resp = requests.get('https://api.postcodes.io/postcodes/BN14 9GB')
resp_data = resp.json()['result']
result_dic = {
'longitude': resp_data['longitude'],
'latitude': resp_data['latitude']
}
result_data = JsonResponse(result_dic)
def result(self):
json_data = self.resp_data()
file_serializer = PostcodeLookupSerializer(json_data, many=True)
return Response(data=file_serializer.data, status=status.HTTP_200_OK)
serializer
class PostcodeLookupSerializer(serializers.Serializer):
postcode = serializers.CharField(required=True)
name = serializers.CharField(required=True)
and url
urlpatterns = [
path('views/', StoreView.as_view(), name='postcode_lookup'),]
how to display a json response into restapi?
I got this error
"detail": "Method \"GET\" not allowed."
You should return data inside response as below
return Response(data=file_serializer.data, status=status.HTTP_200_OK)
So I have this custom register API which registers a user, but when user successfully register, I want it to have this message "You have successfully register an account!" But I tried a different method but get an error instead.
serializer.py
class UserCreate2Serializer(ModelSerializer):
email = EmailField(label='Email Address')
valid_time_formats = ['%H:%M', '%I:%M%p', '%I:%M %p']
birthTime = serializers.TimeField(format='%I:%M %p', input_formats=valid_time_formats, allow_null=True, required=False)
class Meta:
model = MyUser
fields = ['username', 'password', 'email', 'first_name', 'last_name', 'gender', 'nric', 'birthday', 'birthTime']
extra_kwargs = {"password": {"write_only": True}}
def validate(self, data): # to validate if the user have been used
email = data['email']
user_queryset = MyUser.objects.filter(email=email)
if user_queryset.exists():
raise ValidationError("This user has already registered.")
return data
def create(self, validated_data):
username = validated_data['username']
password = validated_data['password']
email = validated_data['email']
first_name = validated_data['first_name']
last_name = validated_data['last_name']
gender = validated_data['gender']
nric = validated_data['nric']
birthday = validated_data['birthday']
birthTime = validated_data['birthTime']
user_obj = MyUser(
username = username,
email = email,
first_name = first_name,
last_name = last_name,
gender = gender,
nric = nric,
birthday = birthday,
birthTime = birthTime,
)
user_obj.set_password(password)
user_obj.save()
return validated
views.py
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
I tried changing this into the serializer
user_obj.set_password(password)
user_obj.save()
content = {'Message': 'You have successfully register an account'}
return content
But got an error instead. I'm unsure how to do the custom response as I only know it is to be done on views.py.
But if I do this on view:
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
def post(self, request):
content = {'Message': 'You have successfully register'}
return Response(content, status=status.HTTP_200_OK)
It will show this even if the validation is incorrect. Please help me as I'm still inexperienced in DRF.
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response({'Message': 'You have successfully register'}, status=status.HTTP_201_CREATED, headers=headers)
from rest_framework import status
from rest_framework.views import exception_handler as base_handler
def exception_handler(exception, context):
"""
Django rest framework for custom exception handler
#exception : Exception
#context : Context
"""
response = base_handler(exception, context)
if response is not None:
response = custom_response(response)
return response
def serializer_errors(data):
"""
Django rest framework serializing the errors
#data : data is python error dictionary
"""
errors = {}
got_msg = False
message = "Bad request."
if isinstance(data, dict):
for key, value in data.items():
try:
if isinstance(value, list):
value = ", ".join(value)
except Exception:
pass
if not got_msg:
if value:
message = value
got_msg = True
errors[key] = value
if not isinstance(message, str):
message = "Bad request"
return errors, message
def error(source, detail, code):
"""
Create python dictionary of error
#source : Where coming the error
#detail : Error detail information
"""
error = {}
error["source"] = source
error["detail"] = detail
if code:
error["code"] = code
return error
def custom_response(response):
"""
Modification the response of django rest framework
#response : Return response
"""
modified_data = {}
modified_data["code"] = response.status_code
modified_data["status"] = get_status(response.status_code)
data, message = serializer_errors(response.data)
modified_data["message"] = message
modified_data["errors"] = data
response.data = modified_data
return response
def get_status(status_code):
"""
Return result base on return http status
#status_code : HTTP status code
"""
result = ""
if status_code == status.HTTP_200_OK:
result = "Success"
elif status_code == status.HTTP_201_CREATED:
result = "Instance create"
elif status_code == status.HTTP_204_NO_CONTENT:
result = "Instance deleted"
elif status_code == status.HTTP_403_FORBIDDEN:
result = "Forbidden error"
elif status_code == status.HTTP_404_NOT_FOUND:
result = "Instance not found"
elif status_code == status.HTTP_400_BAD_REQUEST:
result = "Bad request"
elif status_code == status.HTTP_401_UNAUTHORIZED:
result = "Unauthorized request"
elif status_code == status.HTTP_500_INTERNAL_SERVER_ERROR:
result = "Internal server error"
else:
result = "Unknown error"
return result
Adding a plugin to a page gives an error 'NoneType' object has no attribute 'current_app'.
This is my appplugin code:
class AppPlugin(CMSPluginBase):
name = 'app_plugin'
model = AppInfo
render_template = 'app_plugin.html'
fields = ('title', 'size')
#staticmethod
def _add_app(para, project, context):
count = App.objects.filter(
name=para['name'], project_id=project).count()
if count:
status, message = 'ERROR', 'This app already exists.'
else:
App.objects.create(
name=para['name'],
project_id=project
)
status, message = 'SUCCESS', ''
context['status'] = status
context['message'] = message
return context
#staticmethod
def _modify_app(para, project, context):
count = App.objects.filter(
name=para['name'], project_id=project).count()
if count:
status, message = 'ERROR', 'This app already exists.'
else:
app = App.objects.get(id=para['id'])
app.name = para['name']
app.save()
status, message = 'SUCCESS', ''
context['status'] = status
context['message'] = message
return context
#staticmethod
def _delete_app(para, project, context):
try:
app = App.objects.get(id=para['id'])
except App.DoesNotExist:
context['status'], context[
'message'] = 'ERROR', 'Not found this app.'
return context
if app.testcase_set.count() or app.testsuite_set.count() or \
app.testplan_set.count() or app.testexecution_set.count():
context['status'], context[
'message'] = 'ERROR', 'This app has been used.'
else:
app.delete()
context['status'], context['message'] = 'SUCCESS', ''
return context
#staticmethod
def _search_app(para, project, context):
filter_param = {'project_id': project}
app_name = para.get('app_name', None)
if app_name:
filter_param['name__icontains'] = app_name
context['app_all'] = App.objects.filter(**filter_param).order_by(
'-id')
context['status'] = 'SUCCESS'
context['message'] = ''
return context
#staticmethod
def _add_app_attr(para, project, context):
count = AppAttr.objects.filter(
name=para['name'],
app_id=para['app_id'],
project_id=project).count()
if count:
status, message = 'ERROR', 'This attribute already exists.'
else:
AppAttr.objects.create(
name=para['name'],
app_id=para['app_id'],
project_id=project
)
status, message = 'SUCCESS', ''
context['status'] = status
context['message'] = message
return context
#staticmethod
def _modify_app_attr(para, project, context):
count = AppAttr.objects.filter(
name=para['name'],
app_id=para['app_id'],
project_id=project).count()
if count:
status, message = 'ERROR', 'This attribute already exists.'
else:
attr = AppAttr.objects.get(id=para['id'])
attr.name = para['name']
attr.save()
status, message = 'SUCCESS', ''
context['status'] = status
context['message'] = message
return context
#staticmethod
def _delete_app_attr(para, project, context):
try:
attr = AppAttr.objects.get(id=para['id'])
except AppAttr.DoesNotExist:
context['status'], context[
'message'] = 'ERROR', 'Not found this attribute.'
return context
app = App.objects.get(id=attr.app_id)
if app.testcase_set.count() or app.testsuite_set.count() or \
app.testplan_set.count() or app.testexecution_set.count():
context['status'], context[
'message'] = 'ERROR', 'This attribute has been used.'
else:
attr.delete()
context['status'], context['message'] = 'SUCCESS', ''
return context
def _operate(self, method, param, project, context):
para = json.loads(param)
return eval('self.' + method)(para, project.id, context)
#check_login_required_flag
def render(self, context, instance, placeholder):
if not context['auth_flag']:
return context
config = AppInfo.objects.get(cmsplugin_ptr_id=instance)
argpost = QueryDict.dict(context['request'].POST)
project_name = context['request'].session['project']
project = Project.objects.get(name=project_name)
context['title'] = config.title
context['size'] = config.size
context['app_all'] = App.objects.filter(project_id=project.id).order_by(
'-id')
method = argpost.get('app_method', None)
parameters = argpost.get('app_para', None)
if method and parameters:
context = self._operate(method, parameters, project, context)
# paging processing
app_list, page_range, entry_num = paginator(argpost, context['app_all'])
app_detail = [{'app': app, 'attr': app.appattr_set.all()} for app in
app_list]
context['app_detail'] = app_detail
context['app_count'] = len(context['app_all'])
context['entry_num'] = entry_num
context['page_range'] = page_range
context['app_list'] = app_list
return context