Coverage for src/django_resume/plugins/identity.py: 55%

75 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-10-11 10:47 +0200

1from django import forms 

2from django.core.files.base import ContentFile 

3from django.core.files.storage import default_storage 

4from django.core.files.uploadedfile import InMemoryUploadedFile 

5from django.forms.widgets import ClearableFileInput 

6from django.http import HttpRequest 

7 

8from .base import SimplePlugin, SimpleTemplates, ContextDict 

9 

10 

11class CustomFileObject: 

12 def __init__(self, filename): 

13 self.name = filename 

14 self.url = default_storage.url(filename) 

15 

16 def __str__(self): 

17 return self.name 

18 

19 

20class CustomClearableFileInput(ClearableFileInput): 

21 template_name = "custom_clearable_file_input.html" 

22 

23 def get_context(self, name, value, attrs): 

24 value = CustomFileObject(value) 

25 context = super().get_context(name, value, attrs) 

26 context["widget"]["is_initial"] = self.is_initial(value) 

27 return context 

28 

29 

30class IdentityForm(forms.Form): 

31 template_name = "django_resume/identity/plain/form_as_div.html" 

32 name = forms.CharField(label="Your name", max_length=100, initial="Your name") 

33 pronouns = forms.CharField( 

34 label="Pronouns", max_length=100, initial="your/pronouns" 

35 ) 

36 tagline = forms.CharField( 

37 label="Tagline", max_length=512, initial="Some tagline text." 

38 ) 

39 location_name = forms.CharField( 

40 label="Location", max_length=100, initial="City, Country, Timezone" 

41 ) 

42 location_url = forms.URLField( 

43 label="Location url", 

44 max_length=100, 

45 initial="https://maps.app.goo.gl/TkuHEzeGpr7u2aCD7", 

46 assume_scheme="https", 

47 ) 

48 avatar_img = forms.FileField( 

49 label="Profile Image", 

50 max_length=100, 

51 required=False, 

52 widget=CustomClearableFileInput, 

53 ) 

54 avatar_alt = forms.CharField( 

55 label="Profile photo alt text", 

56 max_length=100, 

57 initial="Profile photo", 

58 required=False, 

59 ) 

60 clear_avatar = forms.BooleanField( 

61 widget=forms.CheckboxInput, initial=False, required=False 

62 ) 

63 email = forms.EmailField( 

64 label="Email address", 

65 max_length=100, 

66 initial="foobar@example.com", 

67 ) 

68 phone = forms.CharField( 

69 label="Phone number", 

70 max_length=100, 

71 initial="+1 555 555 5555", 

72 ) 

73 github = forms.URLField( 

74 label="GitHub url", 

75 max_length=100, 

76 initial="https://github.com/foobar/", 

77 assume_scheme="https", 

78 ) 

79 linkedin = forms.URLField( 

80 label="LinkedIn profile url", 

81 max_length=100, 

82 initial="https://linkedin.com/foobar/", 

83 assume_scheme="https", 

84 ) 

85 mastodon = forms.URLField( 

86 label="Mastodon url", 

87 max_length=100, 

88 initial="https://fosstodon.org/@foobar", 

89 assume_scheme="https", 

90 ) 

91 

92 def __init__(self, *args, **kwargs): 

93 super().__init__(*args, **kwargs) 

94 initial_avatar_img_filename = self.initial.get("avatar_img") 

95 print("initial avatar img: ", initial_avatar_img_filename) 

96 if initial_avatar_img_filename is not None: 96 ↛ 97line 96 didn't jump to line 97 because the condition on line 96 was never true

97 self.fields["avatar_img"].initial = CustomFileObject( 

98 initial_avatar_img_filename 

99 ) 

100 print("initial avatar img: ", self.fields["avatar_img"].initial) 

101 

102 @property 

103 def avatar_img_url(self): 

104 return default_storage.url(self.initial.get("avatar_img", "")) 

105 

106 def clean(self): 

107 # super ugly - FIXME 

108 cleaned_data = super().clean() 

109 avatar_img = cleaned_data.get("avatar_img") 

110 clear_avatar = cleaned_data.get("clear_avatar") 

111 print("cleaned_data: ", cleaned_data) 

112 

113 avatar_handled = False 

114 just_clear_the_avatar = clear_avatar and not hasattr( 

115 avatar_img, "temporary_file_path" 

116 ) 

117 if just_clear_the_avatar: 

118 cleaned_data["avatar_img"] = None 

119 avatar_handled = True 

120 

121 set_new_avatar_image = ( 

122 isinstance(avatar_img, InMemoryUploadedFile) and not avatar_handled 

123 ) 

124 if set_new_avatar_image: 

125 if avatar_img.size > 2 * 1024 * 1024: 

126 raise forms.ValidationError("Image file too large ( > 2mb )") 

127 cleaned_data["avatar_img"] = default_storage.save( 

128 f"uploads/{avatar_img.name}", ContentFile(avatar_img.read()) 

129 ) 

130 avatar_handled = True 

131 

132 keep_current_avatar = ( 

133 not clear_avatar and isinstance(avatar_img, str) and not avatar_handled 

134 ) 

135 if keep_current_avatar: 

136 cleaned_data["avatar_img"] = avatar_img 

137 

138 del cleaned_data["clear_avatar"] # reset the clear_avatar field 

139 return cleaned_data 

140 

141 

142class IdentityPlugin(SimplePlugin): 

143 name: str = "identity" 

144 verbose_name: str = "Identity Information" 

145 templates = SimpleTemplates( 

146 main="django_resume/identity/plain/content.html", 

147 form="django_resume/identity/plain/form.html", 

148 ) 

149 admin_form_class = inline_form_class = IdentityForm 

150 

151 def get_context( 

152 self, 

153 _request: HttpRequest, 

154 plugin_data: dict, 

155 resume_pk: int, 

156 *, 

157 context: ContextDict, 

158 edit: bool = False, 

159 ) -> ContextDict: 

160 context = super().get_context( 

161 _request, plugin_data, resume_pk, context=context, edit=edit 

162 ) 

163 context["avatar_img_url"] = default_storage.url( 

164 plugin_data.get("avatar_img", "") 

165 ) 

166 return context