mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-31 16:07:38 +03:00 
			
		
		
		
	* Update relations.py
Currently if you define the slug field as a nested relationship in a `SlugRelatedField` while many=False, it will cause an attribute error. For example:
For this code:
```
class SomeSerializer(serializers.ModelSerializer):
    some_field= serializers.SlugRelatedField(queryset=SomeClass.objects.all(), slug_field="foo__bar")
```
The POST request (or save operation) should work just fine, but if you use GET, then it will fail with Attribute error:
> AttributeError: 'SomeClass' object has no attribute 'foo__bar'
Thus I am handling nested relation here. Reference: https://stackoverflow.com/questions/75878103/drf-attributeerror-when-trying-to-creating-a-instance-with-slugrelatedfield-and/75882424#75882424
* Fixed test cases
* code comment changes related to slugrelatedfield
* changes based on pre-commit and removed comma which was added accidentally
* fixed primary keys of the mock object
* added more test cases based on review
---------
Co-authored-by: Arnab Shil <arnab.shil@thermofisher.com>
		
	
			
		
			
				
	
	
		
			60 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from operator import attrgetter
 | |
| 
 | |
| from django.core.exceptions import ObjectDoesNotExist
 | |
| from django.urls import NoReverseMatch
 | |
| 
 | |
| 
 | |
| class MockObject:
 | |
|     def __init__(self, **kwargs):
 | |
|         self._kwargs = kwargs
 | |
|         for key, val in kwargs.items():
 | |
|             setattr(self, key, val)
 | |
| 
 | |
|     def __str__(self):
 | |
|         kwargs_str = ', '.join([
 | |
|             '%s=%s' % (key, value)
 | |
|             for key, value in sorted(self._kwargs.items())
 | |
|         ])
 | |
|         return '<MockObject %s>' % kwargs_str
 | |
| 
 | |
| 
 | |
| class MockQueryset:
 | |
|     def __init__(self, iterable):
 | |
|         self.items = iterable
 | |
| 
 | |
|     def __getitem__(self, val):
 | |
|         return self.items[val]
 | |
| 
 | |
|     def get(self, **lookup):
 | |
|         for item in self.items:
 | |
|             if all([
 | |
|                 attrgetter(key.replace('__', '.'))(item) == value
 | |
|                 for key, value in lookup.items()
 | |
|             ]):
 | |
|                 return item
 | |
|         raise ObjectDoesNotExist()
 | |
| 
 | |
| 
 | |
| class BadType:
 | |
|     """
 | |
|     When used as a lookup with a `MockQueryset`, these objects
 | |
|     will raise a `TypeError`, as occurs in Django when making
 | |
|     queryset lookups with an incorrect type for the lookup value.
 | |
|     """
 | |
| 
 | |
|     def __eq__(self):
 | |
|         raise TypeError()
 | |
| 
 | |
| 
 | |
| def mock_reverse(view_name, args=None, kwargs=None, request=None, format=None):
 | |
|     args = args or []
 | |
|     kwargs = kwargs or {}
 | |
|     value = (args + list(kwargs.values()) + ['-'])[0]
 | |
|     prefix = 'http://example.org' if request else ''
 | |
|     suffix = ('.' + format) if (format is not None) else ''
 | |
|     return '%s/%s/%s%s/' % (prefix, view_name, value, suffix)
 | |
| 
 | |
| 
 | |
| def fail_reverse(view_name, args=None, kwargs=None, request=None, format=None):
 | |
|     raise NoReverseMatch()
 |